BeautifulSoup是一個可以從HTML和XML中提取數(shù)據(jù)的Python庫,BeautifulSoup化平淡為神奇,通過定位HTML 標(biāo)簽來格式化和組織復(fù)雜的網(wǎng)絡(luò)信息,有了它的幫助你會節(jié)省數(shù)個小時甚至數(shù)天的時間。BeautifulSoup并不是Python的標(biāo)準(zhǔn)庫所以要額外安裝。我們可以直接pip安裝。安裝完BeautifulSoup之后我們可以安裝一下解析器當(dāng)然也可以不安裝。因?yàn)锽eautifulSoup支持Python標(biāo)準(zhǔn)庫中的HTML解析器,另外兩個解析器分別是lxml和純Python實(shí)的html5lib。你們可能會問既然python的標(biāo)準(zhǔn)庫都有解析器為什么我們還要去安裝額外的呢,自然每一個解析器都有自己的優(yōu)缺點(diǎn)咯。以下是BeautifulSoup4.2.0文檔給出的優(yōu)缺點(diǎn)
python標(biāo)準(zhǔn)庫 , 使用方法:BeautifulSoup(markup,"html.parser") ,優(yōu)勢: 1.python的內(nèi)置標(biāo)準(zhǔn)庫? 2.執(zhí)行速度適中? 3.文檔容錯能力強(qiáng)? ? ? ? ?? 劣勢:? 1.python2.7.2or3.2.2前到的版? ? ? ?2.執(zhí)行速度適中本文檔容錯能力弱
lxml HTML 解析器? ?,使用方法: BeautifulSoup(markup,"lxml")? ? ? ? ? ? 優(yōu)勢1.速度快??2.文檔容錯能力強(qiáng)? ? ? 劣勢:1.需要安裝C語言庫
lxml XML解析器? ?使用方法: BeautifulSoup(markup,["lxml","xml"])? ? ? ? ?優(yōu)勢: 1.速度快? ? ?2.唯一支持XML的解析器 ? ? ? ? ? ? ? ? ? 劣勢? ? 1.需要安裝C語言庫
html5lib? ? ? 使用方法: BeautifulSoup(markup,"html5lib")? ? ? ? ?優(yōu)勢: 1.最好的的兼容性? 2.以瀏覽器的方式解析文檔?? 3.生成HTML5格式的文檔? ? ? ? 劣勢:? 1.速度慢??2.不依賴外部擴(kuò)展
當(dāng)然了如果你和我一樣懶不想去安裝那些擴(kuò)展的
解析器其實(shí)問題也不是很大,Python標(biāo)準(zhǔn)庫中的解析器能過滿足我們絕大多數(shù)的需求
既然安裝完了那么我們就要引用它
from bs4 import BeautifulSoup
講一段文檔傳入BeautifulSoup的構(gòu)造方法就能的到一個文檔對象,可以傳入一個字符串或者文件句柄文檔里面給了一個例子。其中文檔被轉(zhuǎn)換成Unicode,并且HTML的實(shí)例都被轉(zhuǎn)換成Unicode編碼Beautiful Soup選擇最合適的解析器來解析這段文檔,如果手動指定解析器那么Beautiful Soup會選擇指定的解析器來解析文檔
soup = BeautifulSoup("<html>data</html>")
如果你在Windows上直接運(yùn)行指端代碼是會報錯的(linus和Mac上沒有試過),emmm,其實(shí)不能說是報錯,那只是一個warning
warning的大概意思就是:沒有確切的語法分析器被指定所以我為這個系統(tǒng)(lxml)使用最便利的HTML解析器這并不是一個問題,但是如果你在其他系統(tǒng)上使用這段代碼或者在虛擬環(huán)境下使用這段代碼那么她將會使用不同的解析器并且表現(xiàn)的不一樣
為了祛除這個報錯你可以將你的代碼從 BeautifulSoup(YOUR_MARKUP})形式轉(zhuǎn)換為BeautifulSoup(YOUR_MARKUP, "lxml")形式。
也就是說我們要將我們的代碼改成這種形式
soup = BeautifulSoup("<html>data</html>","lxml")
這段代碼的運(yùn)行就沒有問題
BeautifulSoup將復(fù)雜的HTML文檔轉(zhuǎn)換為一個復(fù)雜的樹形結(jié)構(gòu),每個節(jié)點(diǎn)都是python的對象所有對象可以分為四種:Tag,NavigableString?,?BeautifulSoup?,?Comment
那么我們先分別來解釋一下這四個對象是什么意思
Tag:BeautifulSoup 對象通過find 和findAll,或者直接調(diào)用子標(biāo)簽獲取的一列對象或單個對象,就像bs.div.h1
NavigableString:用來表示標(biāo)簽里的文字,不是標(biāo)簽(有些函數(shù)可以操作和生成NavigableString 對象,而不是標(biāo)簽對象)。
BeautifulSoup:被BeautifulSoup解析過的對象
Comment:用來查找HTML 文檔的注釋標(biāo)簽
啥是樹形結(jié)構(gòu)呢,樹形結(jié)構(gòu)可以拿下面這張圖理解一下嘛
我們先來講講Tag,這個對象和XML以及HTML原生文檔中的tag相同,tag中最重要的屬性:name和attributes
name:每一個tag都有自己的名字也就是HTML中標(biāo)簽的名字例如
soup = BeautifulSoup('<b class= "sadfasdf">adfgas</b>','lxml')
tag = soup.b
那么其中b就是這個tag的name我們可以用.name來獲取tag的name例如
tag.name
attributes:一個tag可以有多個attributes。如上一例中有一個class的attributes的值為sadfasdf,tag的attributes的操縱方法和字典相同例:tag['class'] 這可以得出結(jié)果sadfasdf。也可以直接用‘.’來取值比如:.attrs
例:tag.attrs??梢缘贸鼋Y(jié)果:{'class': ['sadfasdf']}。tag的attributes可以修改,其操縱方法也和字典一樣
HTML4中定義了一系列可以包含多個值的attributes,HTML5中移除了一些但是增加了更多。其中最常見的多值屬性就是class? ? ,一個tag可以有多個class,還有一些attributes:?rel?,?rev?,?accept-charset?,?headers?,?accesskey。記住在BeautifulSoup中多值返回類型是list
見以下例子:
cs = BeautifulSoup('<p class="sdf? sadf"></p>')
cs.p["class"]
我們可以的到結(jié)果['sdf', 'sadf']
如果某個attributes看起來好像有多個值,但沒有被定義為多值屬性,那么Beautiful Soup會將這個attributes作為字符串返回
見一下例子:
idb = BeautifulSoup('<p id = "my id"></p>')
idb.p['id']
那么我們將會的到'my id'的結(jié)果
將tag轉(zhuǎn)換為字符串的時候多值屬性將會轉(zhuǎn)換為一個值,還有如果轉(zhuǎn)的文檔格式是xml那么就不包含多值
字符串常常包含在tag內(nèi)也就是<b class = "sdfsadf">pretty good</b>中的pretty good。BeautifulSoup中用NavigableString類型包裝tag的字符串
soup = BeautifulSoup('<b class = "sdfsadf">pretty good</b>')
tag = soup.b
tag.string
可以得出pretty good
再查看一下它的類型
tag中包含的字符串不能編輯,但是可以被替換成其它的字符串,用 replace_with()?方法:
>>>tag.string.replace_with("No away")
>>>tag
可以得到結(jié)果<b class="sdfsadf">No away</b>
順便也說說replace_with()這個方法,replace_with()這個方法用來一處文檔樹中的某段內(nèi)容并用新的tag或者文本節(jié)點(diǎn)代替它。用法:PageElement.replace_with()并會返回被替代的tag或文本節(jié)點(diǎn),可以用來瀏覽或添加到文檔樹其它地方
再來簡單的提一下BeautifulSoup對象
BeautifulSoup對象表示的是一個文檔的全部內(nèi)容,大部分時候可以將它作為tag對象,它支持遍歷文檔樹和搜索文檔樹中的絕大多數(shù)方法。但是BeautifulSoup對象并不是真正的HTML和XML的tag所以沒有name和attributes,但是它有一個值為“[document]”的特殊屬性.name
Comment對象是一個特殊的NavigableString對象,但是在HTML文檔中時會以特殊格式輸出????