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")
  • python自身帶有
  • 速度比較快
  • 能較好兼容 (as of Python 2.7.3 and 3.2.)
不能非常好地兼容(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")    速度非常快
  • The only currently supported XML parser
External C dependency
html5lib BeautifulSoup(markup, "html5lib") 1)兼容性非常好
2)能夠像web瀏覽器一樣解析html頁面
3) Creates valid HTML5
  • 速度非常慢
  • External Python dependency


假設你想追求速度的話。建議使用lxml,假設你使用的python版本號2.x是2.7.3之前的版本號,或者python3.x的是3.2.2之前的版本號。你非常有必要安裝使用html5lib或lxml使用。由於python內建的html解析器不能非常好地適應於這些老版本號。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM