1. 程式人生 > >Python爬蟲系列(四):Beautiful Soup解析HTML之把HTML轉成Python對象

Python爬蟲系列(四):Beautiful Soup解析HTML之把HTML轉成Python對象

調用 nor 結束 版本 現在 name屬性 data 官方文檔 get

在前幾篇文章,我們學會了如何獲取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爬蟲系列(四):Beautiful Soup解析HTML之把HTML轉成Python對象