Python爬蟲系列(四):Beautiful Soup解析HTML之把HTML轉成Python對象
在前幾篇文章,我們學會了如何獲取html文檔內容,就是從url下載網頁。今天開始,我們將討論如何將html轉成python對象,用python代碼對文檔進行分析。
(牛小妹在學校折騰了好幾天,也沒把html文檔給分析出來。接下來的幾篇文章,你可就要好好看了)
Beautiful Soup將複雜HTML文檔轉換成一個複雜的樹形結構,每個節點都是Python對象,所有對象可以歸納為4種: Tag , NavigableString , BeautifulSoup , Comment
Tag 對象與XML或HTML原生文檔中的tag相同
獲取和修改對象的名稱及屬性
from bs4 import BeautifulSoup
#注意,第二個參數一定是這樣用字元串,照官方文檔要報錯。現在BeautifulSoup 是4.6
soup = BeautifulSoup(<b class="boldest">Extremely bold</b>, "lxml-xml")tag = soup.b#b標籤對應的python對象print(type(tag))print(tag.name)#修改標籤 name 不是標籤的name屬性,而是標籤自身tag.name = "blockquote"print(tag)#獲取屬性print(tag[class])
#獲取多個屬性print(tag.attrs)#修改屬性tag[class] = veryboldtag[id] = 1print(tag)#刪除屬性del tag[class]del tag[id]print(tag)
#已經沒有class屬性 獲取就報錯print(tag[class])print(tag.get(class))多指屬性:
是指一個屬性有多個值。
注意:這裡使用的是 lxml-xml 解析器 所以看不出來是多值。用html。parser轉出來的就是多值。
css_soup = BeautifulSoup(<p class="body strikeout"></p>, "lxml-xml")
print(css_soup.p[class])css_soup = BeautifulSoup(<p class="body"></p>, "lxml-xml")print(css_soup.p[class])對應結果:
body strikeout
body
如果某個屬性看起來好像有多個值,但在任何版本的HTML定義中都沒有被定義為多值屬性,那麼Beautiful Soup會將這個屬性作為字元串返回
id_soup = BeautifulSoup(<p id="my id"></p>, "lxml-xml")
#返回的是字元串
print(id_soup.p[id])將tag轉換成字元串時,多值屬性會合併為一個值
rel_soup = BeautifulSoup(<p>Back to the <a rel="index">homepage</a></p>, "lxml-xml")
print(rel_soup.a[rel])rel_soup.a[rel] = [index, contents]print(rel_soup.p)
展示結果:
<p>Back to the <a rel="index contents">homepage</a></p>
注意看a 標籤的rel屬性
可以遍歷的字元串
字元串常被包含在tag內.Beautiful Soup用 NavigableString 類來包裝tag中的字元串
soup = BeautifulSoup(<b class="boldest">Extremely bold</b>)
tag = soup.bprint(tag.string)print(type(tag.string))結果:
Extremely bold
<class bs4.element.NavigableString>
一個 NavigableString 字元串與Python中的Unicode字元串相同,並且還支持包含在 遍歷文檔樹 和 搜索文檔樹 中的一些特性. 通過 unicode() 方法可以直接將 NavigableString 對象轉換成Unicode字元串
from bs4 import BeautifulSoup
from lxml.html.clean import unicodesoup = BeautifulSoup(<b class="boldest">Extremely bold</b>)tag = soup.bunicode_string = unicode(tag.string)print(unicode_string)結果:Extremely bold
tag中包含的字元串不能編輯,但是可以被替換成其它的字元串,用 replace_with() 方法:
from bs4 import BeautifulSoup
soup = BeautifulSoup(<b class="boldest">Extremely bold</b>)tag = soup.btag.string.replace_with("No longer bold")print(tag)結果:
<b class="boldest">No longer bold</b>
注意:
NavigableString 對象支持 遍歷文檔樹 和 搜索文檔樹 中定義的大部分屬性, 並非全部.尤其是,一個字元串不能包含其它內容(tag能夠包含字元串或是其它tag),字元串不支持 .contents 或 .string 屬性或 find() 方法.
如果想在Beautiful Soup之外使用 NavigableString 對象,需要調用 unicode() 方法,將該對象轉換成普通的Unicode字元串,否則就算Beautiful Soup已方法已經執行結束,該對象的輸出也會帶有對象的引用地址.這樣會浪費內存.
BeautifulSoup對象
BeautifulSoup 對象表示的是一個文檔的全部內容.大部分時候,可以把它當作 Tag 對象,它支持 遍歷文檔樹 和 搜索文檔樹 中描述的大部分的方法.
因為 BeautifulSoup 對象並不是真正的HTML或XML的tag,所以它沒有name和attribute屬性.但有時查看它的 .name 屬性是很方便的,所以 BeautifulSoup 對象包含了一個值為 「[document]」 的特殊屬性 .name
知道即可
注釋及特殊字元串
Tag , NavigableString , BeautifulSoup 幾乎覆蓋了html和xml中的所有內容,但是還有一些特殊對象.容易讓人擔心的內容是文檔的注釋部分
from bs4 import BeautifulSoup, CData
markup = "<b><!--Hey, buddy. Want to buy a used parser?--></b>"soup = BeautifulSoup(markup)comment = soup.b.stringprint(type(comment))
# Comment 對象是一個特殊類型的 NavigableString 對象:print(comment)#美化後的輸出結果print(soup.b.prettify())# Beautiful Soup中定義的其它類型都可能會出現在XML的文檔中:# CData , ProcessingInstruction , Declaration , Doctype .與 Comment 對象類似,# 這些類都是 NavigableString 的子類,只是添加了一些額外的方法的字元串獨享.# 下面是用CDATA來替代注釋的例子:cdata = CData("A CDATA block")comment.replace_with(cdata)print(soup.b.prettify())# <b># <![CDATA[A CDATA block]]># </b>推薦閱讀:
※Python從零開始系列連載(14)——Python程序的基本控制流程(中)
※如何用python畫一朵花?
※暴漲1000%,幣盛鏈COL成為又一個橫空出世的暴漲幣
※spyder 如何添加和安裝其他的包?
※「Python與地震工程」單自由度體系求解2