如果僅是想要解析HTML文檔,只要用文檔創(chuàng)建 ?BeautifulSoup
? 對(duì)象就可以了.Beautiful Soup會(huì)自動(dòng)選擇一個(gè)解析器來解析文檔.但是還可以通過參數(shù)指定使用那種解析器來解析當(dāng)前文檔.
?BeautifulSoup
? 第一個(gè)參數(shù)應(yīng)該是要被解析的文檔字符串或是文件句柄,第二個(gè)參數(shù)用來標(biāo)識(shí)怎樣解析文檔.如果第二個(gè)參數(shù)為空,那么Beautiful Soup根據(jù)當(dāng)前系統(tǒng)安裝的庫(kù)自動(dòng)選擇解析器,解析器的優(yōu)先數(shù)序: lxml, html5lib, Python標(biāo)準(zhǔn)庫(kù).在下面兩種條件下解析器優(yōu)先順序會(huì)變化:
要解析的文檔是什么類型: 目前支持, “html”, “xml”, 和 “html5”指定使用哪種解析器: 目前支持, “l(fā)xml”, “html5lib”, 和 “html.parser”
安裝解析器 章節(jié)介紹了可以使用哪種解析器,以及如何安裝.
如果指定的解析器沒有安裝,Beautiful Soup會(huì)自動(dòng)選擇其它方案.目前只有 lxml 解析器支持XML文檔的解析,在沒有安裝lxml庫(kù)的情況下,創(chuàng)建 ?beautifulsoup
? 對(duì)象時(shí)無論是否指定使用lxml,都無法得到解析后的對(duì)象
Beautiful Soup為不同的解析器提供了相同的接口,但解析器本身時(shí)有區(qū)別的.同一篇文檔被不同的解析器解析后可能會(huì)生成不同結(jié)構(gòu)的樹型文檔.區(qū)別最大的是HTML解析器和XML解析器,看下面片段被解析成HTML結(jié)構(gòu):
BeautifulSoup("<a><b /></a>")
# <html><head></head><body><a><b></b></a></body></html>
因?yàn)榭諛?biāo)簽<b />不符合HTML標(biāo)準(zhǔn),所以解析器把它解析成<b></b>
同樣的文檔使用XML解析如下(解析XML需要安裝lxml庫(kù)).注意,空標(biāo)簽<b />依然被保留,并且文檔前添加了XML頭,而不是被包含在<html>標(biāo)簽內(nèi):
BeautifulSoup("<a><b /></a>", "xml")
# <?xml version="1.0" encoding="utf-8"?>
# <a><b/></a>
HTML解析器之間也有區(qū)別,如果被解析的HTML文檔是標(biāo)準(zhǔn)格式,那么解析器之間沒有任何差別,只是解析速度不同,結(jié)果都會(huì)返回正確的文檔樹.
但是如果被解析文檔不是標(biāo)準(zhǔn)格式,那么不同的解析器返回結(jié)果可能不同.下面例子中,使用lxml解析錯(cuò)誤格式的文檔,結(jié)果</p>標(biāo)簽被直接忽略掉了:
BeautifulSoup("<a></p>", "lxml")
# <html><body><a></a></body></html>
使用html5lib庫(kù)解析相同文檔會(huì)得到不同的結(jié)果:
BeautifulSoup("<a></p>", "html5lib")
# <html><head></head><body><a><p></p></a></body></html>
html5lib庫(kù)沒有忽略掉</p>標(biāo)簽,而是自動(dòng)補(bǔ)全了標(biāo)簽,還給文檔樹添加了<head>標(biāo)簽.
使用pyhton內(nèi)置庫(kù)解析結(jié)果如下:
BeautifulSoup("<a></p>", "html.parser")
# <a></a>
與lxml庫(kù)類似的,Python內(nèi)置庫(kù)忽略掉了</p>標(biāo)簽,與html5lib庫(kù)不同的是標(biāo)準(zhǔn)庫(kù)沒有嘗試創(chuàng)建符合標(biāo)準(zhǔn)的文檔格式或?qū)⑽臋n片段包含在<body>標(biāo)簽內(nèi),與lxml不同的是標(biāo)準(zhǔn)庫(kù)甚至連<html>標(biāo)簽都沒有嘗試去添加.
因?yàn)槲臋n片段“<a></p>”是錯(cuò)誤格式,所以以上解析方式都能算作”正確”,html5lib庫(kù)使用的是HTML5的部分標(biāo)準(zhǔn),所以最接近”正確”.不過所有解析器的結(jié)構(gòu)都能夠被認(rèn)為是”正?!钡?
不同的解析器可能影響代碼執(zhí)行結(jié)果,如果在分發(fā)給別人的代碼中使用了 ?BeautifulSoup
? ,那么最好注明使用了哪種解析器,以減少不必要的麻煩.
更多建議: