本章節(jié)總結(jié)了一些 Beautiful Soup 4 的常見(jiàn)問(wèn)題,有遇到相關(guān)問(wèn)題可以按照相應(yīng)的措施進(jìn)行處理。
如果想知道Beautiful Soup到底怎樣處理一份文檔,可以將文檔傳入 ?diagnose()
? 方法(Beautiful Soup 4.2.0中新增),Beautiful Soup會(huì)輸出一份報(bào)告,說(shuō)明不同的解析器會(huì)怎樣處理這段文檔,并標(biāo)出當(dāng)前的解析過(guò)程會(huì)使用哪種解析器:
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é)果可能幫助你找到問(wèn)題的原因,如果不行,還可以把結(jié)果復(fù)制出來(lái)以便尋求他人的幫助
文檔解析錯(cuò)誤有兩種.一種是崩潰,Beautiful Soup嘗試解析一段文檔結(jié)果卻拋除了異常,通常是 ?HTMLParser.HTMLParseError
? .還有一種異常情況,是Beautiful Soup解析后的文檔樹(shù)看起來(lái)與原來(lái)的內(nèi)容相差很多.
這些錯(cuò)誤幾乎都不是Beautiful Soup的原因,這不會(huì)是因?yàn)锽eautiful Soup得代碼寫(xiě)的太優(yōu)秀,而是因?yàn)锽eautiful Soup沒(méi)有包含任何文檔解析代碼.異常產(chǎn)生自被依賴(lài)的解析器,如果解析器不能很好的解析出當(dāng)前的文檔,那么最好的辦法是換一個(gè)解析器.更多細(xì)節(jié)查看 安裝解析器 章節(jié).
最常見(jiàn)的解析錯(cuò)誤是 ?HTMLParser.HTMLParseError: malformed start tag
? 和 ?HTMLParser.HTMLParseError: bad end tag
? .這都是由Python內(nèi)置的解析器引起的,解決方法是 安裝lxml或html5lib
最常見(jiàn)的異?,F(xiàn)象是當(dāng)前文檔找不到指定的Tag,而這個(gè)Tag光是用眼睛就足夠發(fā)現(xiàn)的了. ?find_all()
? 方法返回,而 ?find()
? 方法返回 None .這是Python內(nèi)置解析器的又一個(gè)問(wèn)題: 解析器會(huì)跳過(guò)那些它不知道的tag.解決方法還是 安裝lxml或html5lib
SyntaxError: Invalid syntax
? (異常位置在代碼行: ?ROOT_TAG_NAME = u'[document]'
? ),因?yàn)镻ython2版本的代碼沒(méi)有經(jīng)過(guò)遷移就在Python3中窒息感ImportError: No module named HTMLParser
? 因?yàn)樵赑ython3中執(zhí)行Python2版本的Beautiful SoupImportError: No module named html.parser
? 因?yàn)樵赑ython2中執(zhí)行Python3版本的Beautiful SoupImportError: No module named BeautifulSoup
? 因?yàn)樵跊](méi)有安裝BeautifulSoup3庫(kù)的Python環(huán)境下執(zhí)行代碼,或忘記了BeautifulSoup4的代碼需要從 ?bs4
? 包中引入ImportError: No module named bs4
? 因?yàn)楫?dāng)前Python環(huán)境下還沒(méi)有安裝BeautifulSoup4默認(rèn)情況下,Beautiful Soup會(huì)將當(dāng)前文檔作為HTML格式解析,如果要解析XML文檔,要在 ?BeautifulSoup
? 構(gòu)造方法中加入第二個(gè)參數(shù) “xml”:
soup = BeautifulSoup(markup, "xml")
當(dāng)然,還需要 安裝lxml
BeautifulSoup
? 的構(gòu)造方法中中指定解析器UnicodeEncodeError: 'charmap' codec can't encode character u'\xfoo' in position bar
? (或其它類(lèi)型的 ?UnicodeEncodeError
? )的錯(cuò)誤,主要是兩方面的錯(cuò)誤(都不是Beautiful Soup的原因),第一種是正在使用的終端(console)無(wú)法顯示部分Unicode,參考 Python
wiki ,第二種是向文件寫(xiě)入時(shí),被寫(xiě)入文件不支持部分Unicode,這時(shí)只要用 ?u.encode("utf8")
? 方法將編碼轉(zhuǎn)換為UTF-8.KeyError: [attr]
? 因?yàn)檎{(diào)用 ?tag['attr']
? 方法而引起,因?yàn)檫@個(gè)tag沒(méi)有定義該屬性.出錯(cuò)最多的是 ?KeyError: 'href'
? 和 ?KeyError: 'class'
? .如果不確定某個(gè)屬性是否存在時(shí),用 ?tag.get('attr')
? 方法去獲取它,跟獲取Python字典的key一樣AttributeError: 'ResultSet' object has no attribute 'foo'
? 錯(cuò)誤通常是因?yàn)榘?nbsp;?find_all()
? 的返回結(jié)果當(dāng)作一個(gè)tag或文本節(jié)點(diǎn)使用,實(shí)際上返回結(jié)果是一個(gè)列表或 ?ResultSet
? 對(duì)象的字符串,需要對(duì)結(jié)果進(jìn)行循環(huán)才能得到每個(gè)節(jié)點(diǎn)的 ?.foo
? 屬性.或者使用 ?find()
? 方法僅獲取到一個(gè)節(jié)點(diǎn)AttributeError: 'NoneType' object has no attribute 'foo'
? 這個(gè)錯(cuò)誤通常是在調(diào)用了 ?find()
? 方法后直節(jié)點(diǎn)取某個(gè)屬性 .foo 但是 ?find()
? 方法并沒(méi)有找到任何結(jié)果,所以它的返回值是 ?None
? .需要找出為什么 ?find()
? 的返回值是 ?None
? .Beautiful Soup對(duì)文檔的解析速度不會(huì)比它所依賴(lài)的解析器更快,如果對(duì)計(jì)算時(shí)間要求很高或者計(jì)算機(jī)的時(shí)間比程序員的時(shí)間更值錢(qián),那么就應(yīng)該直接使用 lxml .
換句話(huà)說(shuō),還有提高Beautiful Soup效率的辦法,使用lxml作為解析器.Beautiful Soup用lxml做解析器比用html5lib或Python內(nèi)置解析器速度快很多.
安裝 cchardet 后文檔的解碼的編碼檢測(cè)會(huì)速度更快
解析部分文檔 不會(huì)節(jié)省多少解析時(shí)間,但是會(huì)節(jié)省很多內(nèi)存,并且搜索時(shí)也會(huì)變得更快.
更多建議: