Python的html解析器
转自https://blog.csdn.net/jqh2002_blog/article/details/24842217
其实比较不同的解析器对html的处理能力是有点麻烦的,因为它们处理的步骤并不完全相同的:
1. 解析HTML:能读入
2. 解析为某个对象:能处理
3. 序列化:能输出
各个解析器做的可能是三件事中的某部分。基本上常见的解析器调查一下:
lxml: 三样都干,而且还可以使用参数指定其他几种解析器。
BeautifulSoup: 三样都干。
html5lib: 可以解析,但是它的序列化和对象化就做的一般。
ElementTree: 对象化和序列化xml,html支持一般,同时它不具备解析功能,所以通常是用html5lib把文档解析后交给它。
cElementTree: 作为c扩展的一个对象化库。
HTMLParser: 有名的解析库。但不能生成任何结果树。
htmlfill: 这个库实际上使用了HTMLParser,不过在解析的时候把解析后的结果稍微结构化了一下。
Genshi: 三样都干。
xml.dom.minidom: 对象化的库,可以把html5lib的解析结果作为输入。这个是python内置的库,但是,相信本座,不用它为好。
在实际做的时候,本座重点考察了lxml,因为它是基于c的libxml2库的,想必速度会很快。看它官网上的结论,也是很漂亮。不过官网都是自说自话,当然不能全信,因此本座也有做自己的测试。
测试使用的基准文件是Java JDK的Docs(懒得找别的了)。代码就不贴了,反正就是解析。图片是用google的chart api来生成的,大概的代码如下:
def make_chart(data, size_x=400, size_y=None, graph_type='bhs', name_format='%(name)s'):
url = 'http://chart.apis.google.com/chart?'
params = {}
if size_y is None:
size_y = len(data)*30
params['chs'] = '%sx%s' % (size_x, size_y)
numbers = [number for name, number in data]
params['chd'] = 'e:' + ''.join(list(encode_numbers(numbers)))
names = [name_format % dict(name=name, number=number) for name, number in data]
params['chxl'] = '0:|%s|' % '|'.join(reversed(names))
params['chxt'] = 'y'
params['cht'] = graph_type
return url + urllib.urlencode(params)
digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-.'
其中的encode_numbers主要是用来做输入数据的scale:
def encode_numbers(numbers, lowest=0):
"""
Encodes numbers over the range of 0-4095
"""
if lowest is None:
lowest = min(numbers)
highest = max(numbers)
range = highest-lowest
for number in numbers:
adjusted = int((number - lowest) * 4095 / range)
assert adjusted >= 0 and adjusted <= 4095, 'Out of range: %r' % adjusted
yield digits[adjusted / 64] + digits[adjusted % 64]
解析
可以看到,lxml居然是最快的,比HTMLParser的速度都快(要知道后面这个老兄可是别的什么都不做),原因可能是lxml在内存中生成了一棵树吧。 xml.dom.minidom是慢到龟速了,Genshi算是速度不错的,但是也是所有解析器中最容易出错的。相对而言,html5lib、lxml和BeautifulSoup是最稳定的。尤其是html5lib,可以(从理论上而言)保证解析的鲁棒性。
序列化
虽然lxml又像博尔特一样跑在前面,但是我们可以看到对绝大多数包而言序列化都不算是费时的活。同时,minidom有一次垫底,这下你知道本座为什么叫你不要考虑用它了吧。
结论
由于源于c,实验之前本座也猜想lxml会是更快的那位,但是没有想到它有这么快。后续可能的话,应该再对内存占用率做一个比较。但由于调用的大都是c而不是python来完成运行,相信比较的结果也会比较乐观。因此,本座在后面的博客搬家以及将来一切与xml/html解析相关的工作就交给它了。
这次实验还有一个结论。长期以来,对xml/html的解析,把文件作为一个输入流而不是对象的方式读入一直被认为是最佳方案。拍拍脑袋我们大概可以想象,不断由事件驱动读入token会比在内存中储存整个对象树要。HTMLParser 和Genshi 等解析器都是采用的这种方式。不过通过这次实验我们可以看到,只要我们处理的不是数个G的怪物文件,用持有对象的lxml和ElementTree这样的库其实是更好的选择,因为对对象的处理总是比数据流来得自然很多。即使你真的有非常奇怪的需求,需要处理超大的文件,lxml也有参数可供选择。
转自:http://www.cnblogs.com/wzzkaifa/p/7111431.html
Beautiful Soup解析器比較
·Beautiful Soup支持各种html解析器。包含python自带的标准库。还有其它的很多第三方库模块。
当中一个就是lxml parser,至于lxml parser的安装,能够通过下面方法安装:
1)easy_install lxml 2)pip install lxml
另外。python对于模块的安装,能够查看博客说明。分为两种:easy_install 和 pip.
第二种纯python解析器为html5lib解析器。能够像web浏览器那样解析html页面,你能够通过以下两种方式安装html5lib:
1)easy_install html5lib 2)pip install html5lib
以下对各种html解析器的优缺点做一下对照:
解析器 | 用法 | 长处 | 缺点 |
---|---|---|---|
Python’s html.parser | BeautifulSoup(markup,"html.parser") |
|
不能非常好地兼容(before Python 2.7.3 or 3.2.2) |
lxml’s HTML parser | BeautifulSoup(markup,"lxml") |
|
External C dependency |
lxml’s XML parser | BeautifulSoup(markup, "lxml-xml") BeautifulSoup(markup,"xml") | 速度非常快
|
External C dependency |
html5lib | BeautifulSoup(markup, "html5lib") | 1)兼容性非常好 2)能够像web浏览器一样解析html页面 3) Creates valid HTML5 |
|
假设你想追求速度的话。建议使用lxml,假设你使用的python版本号2.x是2.7.3之前的版本号,或者python3.x的是3.2.2之前的版本号。你非常有必要安装使用html5lib或lxml使用。由于python内建的html解析器不能非常好地适应于这些老版本号。