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] = verybold

tag[id] = 1

print(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.b

print(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 unicode

soup = BeautifulSoup(<b class="boldest">Extremely bold</b>)

tag = soup.b

unicode_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.b

tag.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.string

print(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

TAG:爬蟲 | Python | 大數據 |