HTMLParser 是一个python自带的库,使用它可以很方便的解析html.
使用HTMLPaser时应先生成它的一个子类,并且对handle_starttag或handle_data之类的事件处理方法进行覆盖
HTMLParser的一些相关方法如下
handle_starttag(tag,attrs) |
找到开始标签是调用。attrs是(名称,值)对的序列 |
handle_startendtag(tag,attrs) |
使用空标签是调用 |
handle_endtag(tag) |
找到结束标签时调用 |
handle_data(data) |
使用文本数据时调用 |
handle_charref(ref) |
当使用&#ref;形式的实体是调用 |
handle_entityref(name) |
当使用&name;形式的实体是调用 |
handle_comment(data) |
注释时调用 |
handle_decl(decl) |
声明<!...>形式时调用 |
handle_pi(data) |
处理指令时调用 |
本文主要讲解常用的三个方法:
handle_starttag
handle_data
handle_endtag
假设我们的目的是对htlm文本data提取 名称:PyCon CZ 2017 时间:09 June
data = r''' <li> <h3 class="event-title"><a href="/events/python-events/523/">PyCon Taiwan 2017</a></h3> <p> <time datetime="2017-06-06T00:00:00+00:00">06 June – 12 June <span class="say-no-more"> 2017</span></time> <span class="event-location">Academia Sinica, 128 Academia Road, Section 2, Nankang, Taipei 11529, Taiwan</span> </p> </li> <li> <h3 class="event-title"><a href="/events/python-events/513/">PyCon CZ 2017</a></h3> <p>
<span class="event-location">Prague, Czechia</span> </p> </li>'''
1 from HTMLParser import HTMLParser 2 3 class scraper(HTMLParser): 4 def __init__(self): 5 6 HTMLParser.__init__(self) 7 self.a_flag=False 8 self.time_flag=False 9 10 self.events=[] 11 def handle_starttag(self, tag, attrs): 12 if tag=='a' and attrs[0][1]=="/events/python-events/513/": 13 self.a_flag=True 14 15 if tag=='time' and attrs[0][1]=='2017-06-09T00:00:00+00:00': 16 self.time_flag=True 17 18 19 20 def handle_data(self, data): 21 if self.a_flag: 22 self.events.append(data) 23 if self.time_flag: 24 self.events.append(data) 25 self.time_flag=False 26 27 28 def handle_endtag(self, tag): 29 if tag=="a": 30 self.a_flag=False
首先创建子类继承HTMLParser
覆盖 handle_starttag
当遇到标签 a 且 href属性的值为“/events/python-events/513/”时设置self.a_flag :Ture
这时
<a href="/events/python-events/513/">PyCon CZ 2017</a>
data 为PyCon CZ 2017
在handle_data中添加 data
而在 time标签中的 因为– 的存在会分为两个data
所以在第一次添加data后 将self.time_flag设为Flase
<time datetime="2017-06-09T00:00:00+00:00">09 June – 12 June <span class="say-no-more"> 2017</span></time>
在handle_endtag 中设置遇到</a>后 将self.a_flag设为False 这样后面遇到的 <a>标签的data就不会被写入
最后调用feed方法运行这个解析器
ep = scraper() ep.feed(data) for x in ep.events: print x
输出:
PyCon CZ 2017
09 June