Beautiful Soup 4 常見問題

2021-05-24 09:15 更新

本章節(jié)總結(jié)了一些 Beautiful Soup 4 的常見問題,有遇到相關(guān)問題可以按照相應(yīng)的措施進行處理。

代碼診斷

如果想知道Beautiful Soup到底怎樣處理一份文檔,可以將文檔傳入 ?diagnose()? 方法(Beautiful Soup 4.2.0中新增),Beautiful Soup會輸出一份報告,說明不同的解析器會怎樣處理這段文檔,并標出當(dāng)前的解析過程會使用哪種解析器:

from bs4.diagnose import diagnose
data = open("bad.html").read()
diagnose(data)

# Diagnostic running on Beautiful Soup 4.2.0
# Python version 2.7.3 (default, Aug  1 2012, 05:16:07)
# I noticed that html5lib is not installed. Installing it may help.
# Found lxml version 2.3.2.0
#
# Trying to parse your data with html.parser
# Here's what html.parser did with the document:
# ...

?diagnose()? 方法的輸出結(jié)果可能幫助你找到問題的原因,如果不行,還可以把結(jié)果復(fù)制出來以便尋求他人的幫助

文檔解析錯誤

文檔解析錯誤有兩種.一種是崩潰,Beautiful Soup嘗試解析一段文檔結(jié)果卻拋除了異常,通常是 ?HTMLParser.HTMLParseError? .還有一種異常情況,是Beautiful Soup解析后的文檔樹看起來與原來的內(nèi)容相差很多.

這些錯誤幾乎都不是Beautiful Soup的原因,這不會是因為Beautiful Soup得代碼寫的太優(yōu)秀,而是因為Beautiful Soup沒有包含任何文檔解析代碼.異常產(chǎn)生自被依賴的解析器,如果解析器不能很好的解析出當(dāng)前的文檔,那么最好的辦法是換一個解析器.更多細節(jié)查看 安裝解析器 章節(jié).

最常見的解析錯誤是 ?HTMLParser.HTMLParseError: malformed start tag? 和 ?HTMLParser.HTMLParseError: bad end tag? .這都是由Python內(nèi)置的解析器引起的,解決方法是 安裝lxml或html5lib

最常見的異?,F(xiàn)象是當(dāng)前文檔找不到指定的Tag,而這個Tag光是用眼睛就足夠發(fā)現(xiàn)的了. ?find_all()? 方法返回,而 ?find()? 方法返回 None .這是Python內(nèi)置解析器的又一個問題: 解析器會跳過那些它不知道的tag.解決方法還是 安裝lxml或html5lib

版本錯誤

  • ?SyntaxError: Invalid syntax? (異常位置在代碼行: ?ROOT_TAG_NAME = u'[document]'? ),因為Python2版本的代碼沒有經(jīng)過遷移就在Python3中窒息感
  • ?ImportError: No module named HTMLParser? 因為在Python3中執(zhí)行Python2版本的Beautiful Soup
  • ?ImportError: No module named html.parser? 因為在Python2中執(zhí)行Python3版本的Beautiful Soup
  • ?ImportError: No module named BeautifulSoup? 因為在沒有安裝BeautifulSoup3庫的Python環(huán)境下執(zhí)行代碼,或忘記了BeautifulSoup4的代碼需要從 ?bs4? 包中引入
  • ?ImportError: No module named bs4? 因為當(dāng)前Python環(huán)境下還沒有安裝BeautifulSoup4

解析成XML

默認情況下,Beautiful Soup會將當(dāng)前文檔作為HTML格式解析,如果要解析XML文檔,要在 ?BeautifulSoup? 構(gòu)造方法中加入第二個參數(shù) “xml”:

soup = BeautifulSoup(markup, "xml")

當(dāng)然,還需要 安裝lxml

解析器的錯誤

  • 如果同樣的代碼在不同環(huán)境下結(jié)果不同,可能是因為兩個環(huán)境下使用不同的解析器造成的.例如這個環(huán)境中安裝了lxml,而另一個環(huán)境中只有html5lib, 解析器之間的區(qū)別 中說明了原因.修復(fù)方法是在 ?BeautifulSoup? 的構(gòu)造方法中中指定解析器
  • 因為HTML標簽是 大小寫敏感 的,所以3種解析器再出來文檔時都將tag和屬性轉(zhuǎn)換成小寫.例如文檔中的 <TAG></TAG> 會被轉(zhuǎn)換為 <tag></tag> .如果想要保留tag的大寫的話,那么應(yīng)該將文檔 解析成XML .

雜項錯誤

  • ?UnicodeEncodeError: 'charmap' codec can't encode character u'\xfoo' in position bar? (或其它類型的 ?UnicodeEncodeError? )的錯誤,主要是兩方面的錯誤(都不是Beautiful Soup的原因),第一種是正在使用的終端(console)無法顯示部分Unicode,參考 Python wiki ,第二種是向文件寫入時,被寫入文件不支持部分Unicode,這時只要用 ?u.encode("utf8")? 方法將編碼轉(zhuǎn)換為UTF-8.
  • ?KeyError: [attr]? 因為調(diào)用 ?tag['attr']? 方法而引起,因為這個tag沒有定義該屬性.出錯最多的是 ?KeyError: 'href'? 和 ?KeyError: 'class'? .如果不確定某個屬性是否存在時,用 ?tag.get('attr')? 方法去獲取它,跟獲取Python字典的key一樣
  • ?AttributeError: 'ResultSet' object has no attribute 'foo'? 錯誤通常是因為把 ?find_all()? 的返回結(jié)果當(dāng)作一個tag或文本節(jié)點使用,實際上返回結(jié)果是一個列表或 ?ResultSet? 對象的字符串,需要對結(jié)果進行循環(huán)才能得到每個節(jié)點的 ?.foo? 屬性.或者使用 ?find()? 方法僅獲取到一個節(jié)點
  • ?AttributeError: 'NoneType' object has no attribute 'foo'? 這個錯誤通常是在調(diào)用了 ?find()? 方法后直節(jié)點取某個屬性 .foo 但是 ?find()? 方法并沒有找到任何結(jié)果,所以它的返回值是 ?None? .需要找出為什么 ?find()? 的返回值是 ?None? .

如何提高效率

Beautiful Soup對文檔的解析速度不會比它所依賴的解析器更快,如果對計算時間要求很高或者計算機的時間比程序員的時間更值錢,那么就應(yīng)該直接使用 lxml .

換句話說,還有提高Beautiful Soup效率的辦法,使用lxml作為解析器.Beautiful Soup用lxml做解析器比用html5lib或Python內(nèi)置解析器速度快很多.

安裝 cchardet 后文檔的解碼的編碼檢測會速度更快

解析部分文檔 不會節(jié)省多少解析時間,但是會節(jié)省很多內(nèi)存,并且搜索時也會變得更快.


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號