摘抄自:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014320023122880232500da9dc4a4486ad00426f081c15000

如果要编写一个搜索引擎,第一步是用爬虫把目标网站的页面抓下来,第二步就是解析该HTML页面,看看里面的内容到底是新闻、图片还是视频。

假设第一步已经完成了,第二步应该如何解析HTML呢?

HTML本质上是XML的子集,但是HTML的语法没有XML那么严格,所以不能用标准的DOM或SAX来解析HTML。

Python提供了HTMLParser来非常方便地解析HTML,只需简单几行代码:

from html.parser import HTMLParser
from html.entities import name2codepoint class MyHTMLParser(HTMLParser): def handle_starttag(self, tag, attrs):
print('<%s>' % tag) def handle_endtag(self, tag):
print('</%s>' % tag) def handle_startendtag(self, tag, attrs):
print('<%s/>' % tag) def handle_data(self, data):
print(data) def handle_comment(self, data): # 解析评论
print('<!--', data, '-->') def handle_entityref(self, name): # 解析实体
print('&%s:' % name) def handle_charref(self, name):
print('&#%s:' % name) if __name__=='__main__':
parser = MyHTMLParser()
parser.feed('''<html>
<head></head>
<body>
<!-- test html parser -->
<p>Some <a href=\"#\">html</a> HTML&nbsp;tutorial...<br>END</p>
</body>
</html>''')
# HTML 中的常用字符实体是不间断空格(&nbsp;)。
# 浏览器总是会截短 HTML 页面中的空格。如果您在文本中写 10 个空格,
# 在显示该页面之前,浏览器会删除它们中的 9 个。如需在页面中增加空格的数量,
# 您需要使用 &nbsp; 字符实体。

结果:

<html>

<head>
</head> <body> <!-- test html parser --> <p>
Some
<a>
html
</a>
HTML tutorial...
<br>
END
</p> </body> </html>

feed()方法可以多次调用,也就是不一定一次把整个HTML字符串都塞进去,可以一部分一部分塞进去。

特殊字符有两种,一种是英文表示的&nbsp;,一种是数字表示的Ӓ,这两种字符都可以通过Parser解析出来。

小结

利用HTMLParser,可以把网页中的文本、图像等解析出来。

练习

找一个网页,例如https://www.python.org/events/python-events/,用浏览器查看源码并复制,然后尝试解析一下HTML,输出Python官网发布的会议时间、名称和地点。

# -*- coding: utf-8 -*-
# 建议1: 子类在重载构造函数时不要忘了调用父类的构造函数
# 建议2: HTMLParser的attrs是一个元素为tuple的list
# 建议3: 调用类属性时,一定要加self, 否则相当于声明了新的临时变量 from html.parser import HTMLParser
from html.entities import name2codepoint
from urllib import request class MyHTMLParser(HTMLParser): # 解析一下HTML,输出Python官网发布的会议时间、名称和地点。
def __init__(self):
super().__init__()
self._event_title = []
self._event_location = []
self._event_time = []
self._reading_title = False
self._reading_time = False
self._reading_location = False # 解析头标签
def handle_starttag(self, tag, attrs):
if tag == 'time':
self._reading_time = True
if len(attrs) >= 1:
if tag == 'h3' and attrs[0][1] == 'event-title':
self._reading_title = True
if tag == 'span' and attrs[0][1] == 'event-location':
self._reading_location = True # 解析内容
def handle_data(self, data):
if self._reading_title:
self._event_title.append(data)
self._reading_title = False
if self._reading_time:
self._event_time.append(data)
self._reading_time = False
if self._reading_location:
self._event_location.append(data)
self._reading_location = False @property
def data(self):
self._data = []
for i in range(len(self._event_title)):
dic = {}
dic["title"] = self._event_title[i]
dic["time"] = self._event_time[i]
dic["location"] = self._event_location[i]
self._data.append(dic)
return self._data def getHtml():
with request.urlopen('https://www.python.org/events/python-events/') as f:
data = f.read().decode('utf-8')
return data parser = MyHTMLParser()
parser.feed(getHtml())
for item in parser.data:
print(str(item))

结果:

{'time': '07 Sept. – 11 Sept. ', 'location': 'Waseda University, Nishi-Waseda Campus, Building 63, Tokyo, Japan', 'title': 'PyCon JP 2017'}
{'time': '08 Sept. – 11 Sept. ', 'location': 'Universidade de Caxias do Sul (UCS), Caxias do Sul, Rio Grande do Sul, Brazil', 'title': 'Python Sul'}
{'time': '15 Sept. – 17 Sept. ', 'location': 'Lagos, Nigeria', 'title': 'PyCon Nigeria 2017'}
{'time': '21 Sept. – 25 Sept. ', 'location': 'Toulouse, France', 'title': 'PyCon FR 2017'}
{'time': '22 Sept. – 25 Sept. ', 'location': 'Caceres, Spain', 'title': 'PyConES17'}
{'time': '28 Sept. – 30 Sept. ', 'location': 'United States International University, Nairobi, Kenya', 'title': 'PyConKE 2017'}
{'time': '28 Aug. – 02 Sept. ', 'location': 'Erlangen, Germany', 'title': 'EuroSciPy 2017'}
{'time': '26 Aug. – 28 Aug. ', 'location': 'Kuala Lumpur, Malaysia', 'title': 'PyCon APAC 2017'}

最新文章

  1. Python 9X9乘法口诀表
  2. db2简单语句记录
  3. 【腾讯云】腾讯云服务器搭建ftp服务器
  4. Winform基础
  5. PC-信使服务之不用聊天软件也能通信
  6. ubuntu 安装qq
  7. 深入浅出Node.js (6) - 理解Buffer
  8. 手算KMP匹配的Next值和Nextval值
  9. Github上四种Lisp方言的流行度 | 肉山博客 (Wenshan's Blog)
  10. 事件聚合IEventAggregator和 Ihandle&lt;T&gt;
  11. RMQ问题第一弹
  12. win10 uwp 分治法
  13. spring boot https --restful接口篇
  14. Android SingleTask使用注意点
  15. C#_反射机制
  16. js日常
  17. Python redis 简单介绍
  18. OpenTSDB安装
  19. fedora27安装谷歌浏览器Chrome
  20. JQuery Mobile - 需要注意问题!

热门文章

  1. C++:const_cast的简单理解
  2. 如何利用Xshell在Linux下安装jdk
  3. C++ Primer Plus学习:第六章
  4. CentOS 7 网卡命名修改为eth0格式
  5. Struts2(七)
  6. spring复杂数据类型传递
  7. 【beta】nice!-------约吧NABCD
  8. CentOS 7 U盘安装问题解决
  9. 初探Android动画之门
  10. postman 断言学习