这是从用Python开发开始到现在第二次使用HTMLParser模块进行html解析了,第一次用的时候,由于是刚刚接触Python,对其中的一些用法不是很理解,因为赶进度,虽然照着参考资料也写出来了,但是其中的原理还是不怎么了解。第二次用的时候,有一定的经验了,对Python的理解也更加深刻了,所以第二次用的时候,对HTMLParser模块的一些用法不像第一次用时那么茫然。结合鄙人第二次用该模块的经验,来讲讲HTMLParser模块的基本使用方法,希望对你有帮助。
HTMLParser是python用来解析html的模块。它可以分析出html里面的标签、数据等等,是一种处理html的简便途径。HTMLParser采用的是一种事件驱动的模式,当HTMLParser找到一个特定的标记时,它会去调用一个用户定义的函数,以此来通知程序处理。它主要的用户回调函数的命名都是以handler_开头的,都是HTMLParser的成员函数。当我们使用时,就从HTMLParser派生出新的类,然后重新定义这几个以handler_开头的函数即可。这几个函数包括:
handle_startendtag(tag, attrs) 处理开始标签和结束标签
handle_starttag(tag, attrs) 处理开始标签,比如<xx>
handle_endtag(tag) 处理结束标签,比如</xx>
handle_charref(name) 处理特殊字符串,就是以&#开头的,一般是内码表示的字符
handle_entityref(name) 处理一些特殊字符,以&开头的,比如
handle_data(data) 处理数据,就是<xx>data</xx>中间的那些数据
handle_comment(data) 处理注释
handle_decl(decl) 处理<!开头的,比如<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
handle_pi(data) 处理形如<?instruction>的东西
tag是的html标签,attrs是 (属性,值)元组(tuple)的列表(list).
HTMLParser自动将tag和attrs都转为小写。
下面以从中国银行官网上解析html文件以获取实时汇率(这就是我第二此用该模块时的解析任务)为例,来定义一个HTMLParser派生类。
在构造这个派生类之前,肯定要分析网页的源码的,找出你要获取的那一个值,在此不做介绍。直接上代码了,要仔细理解
#coding=utf-8
import HTMLParser
import requests
class MyHTMLParser(HTMLParser.HTMLParser):
"""
"""
def __init__(self):
HTMLParser.HTMLParser.__init__(self)
self.result = []#记录结果
self.flag = False#标记
def handle_starttag(self,tag,attrs):
if tag == "td" and self.flag == False and len(attrs) == 0:
#attrs(属性,值)元组(tuple)的列表(list),由于我要获取的值的html标签的没有属性
#所以要求它长度0以排除其它有属性的标签,缩小获取结果的范围。
#如果有属性的话,attrs不会为空,它是元组列表可以用条件语句来判断
self.flag = True
def handle_end(self,tag):
if tag == "td" and self.flag == True:
self.flag = False
def handle_data(self, data):
if self.flag == True:
self.result.append(data)
上面代码不难理解,都是重载HTMLParser类里的方法。
再接着就是爬取网页了,获取数据,代码如下:
def _filter_string(string):
"""
除去字符串中的空格,换行等等
由于网页源码中空格、换行符等会使返回的结果中带有换行符(\t)等,所以在此除去,
其实也可以得到结果(返回的结果是个列表)后用列表的内建方法除去这些带有换行符的元素,
其实这样用‘+’拼接字符串的效率很低,这个问题我也是刚刚发现,过段时间在研究一下,
找到了好的方法,再跟大家分享下。
"""
s = ''
for one in string:
if one != '\n' and one != '\r' and one != '\t' and one != ' ':
s = s + one
return s
def get_rate():
"""
获取汇率
Returns:
"""
url = "http://srh.bankofchina.com/search/whpj/search.jsp"
headers = {'user-agent':'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:46.0) Gecko/20100101 Firefox/46.0'}
usd_data = {
'pjname':1316,#美元在中国银行官网的代码
}
hkd_data = {
'pjname':1315,#港币在中国银行官网的代码
}
usd_result = requests.post(url, data=usd_data, headers=headers)
hkd_result = requests.post(url, data=hkd_data, headers=headers)
usd_parser = MyHTMLParser()
hkd_parser = MyHTMLParser()
usd_text = usd_result.text
hkd_text = hkd_result.text
# text = _filter_string(text)
usd_text = _filter_string(usd_text)
hkd_text = _filter_string(hkd_text)
usd_parser.feed(usd_text)
usd_parser.close()
# print usd_result.text
hkd_parser.feed(hkd_text)
hkd_parser.close()
usd_start = usd_parser.result.index(u"美元") # 美元第一个出现的位置是最新值
usd_rate = usd_parser.result[usd_start + 3]
usd_rate = float(usd_rate) / 100 # 最新美元汇率
usd_uptime = usd_parser.result[usd_start + 7] # 发布时间
hkd_start = hkd_parser.result.index(u"港币")
hkd_rate = hkd_parser.result[hkd_start + 3]
hkd_rate = float(hkd_rate) / 100
hkd_uptime = hkd_parser.result[hkd_start + 7] # 发布时间
return usd_rate, usd_uptime, hkd_rate, hkd_uptime
HTMLParser类的其它一些方法:
HTMLParser.reset()
重置该实例。失去所有未处理的数据。这个在实例化对象时被隐含地调用。
HTMLParser.feed(data)
提供一些文本给解析器。在由完整元素组成的限度内进行处理,不完整的数据被缓冲直到更多的数据提供或者close()被调用。
HTMLParser.close()
强制将所有的缓冲数据按跟在结束标记的数据一样进行处理。该方法可以通过派生类定义对输入结尾的额外处理来进行重定义,但是重定义的版本应该总是调用HTMLParser基类方法close()
HTMLParser.getpos()
返回当前行数和位移值。
HTMLParser.get_starttag_text()
返回当前位置最近的开始标签的内容
这是给公司内部财务人员记账用的,所以做成了API供调用。隐约感觉上面代码最后几行获取结果的方法不是最佳方法,如果你有更好的方法,欢迎您与我分享,如果我找到了更好的我会及时分享给大家。
当然,如果是个简单的任务,用HTMLParser模块抓取一些想要的数据还是绰绰有余,如果是复杂的任务,有一定要求(比如性能要求)的任务,那就要用第三方库,比如Beautiful Soup,不过这个库我没用过,有时间研究一下,然后再和大家分享一下我的学习习得。
转载于:https://blog.51cto.com/11026142/1853831