国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Python3網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)---29、解析庫的使用:BeautifulSoup

MockingBird / 2272人閱讀

摘要:解析器在解析的時(shí)候?qū)嶋H上是依賴于解析器的,它除了支持標(biāo)準(zhǔn)庫中的解析器,還支持一些第三方的解析器比如,下面我們對(duì)支持的解析器及它們的一些優(yōu)缺點(diǎn)做一個(gè)簡單的對(duì)比。

上一篇文章:Python3網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)---28、解析庫的使用:XPath
下一篇文章:Python3網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)---30、解析庫的使用:PyQuery

前面我們介紹了正則表達(dá)式的相關(guān)用法,但是一旦正則寫的有問題,可能得到的就不是我們想要的結(jié)果了,而且對(duì)于一個(gè)網(wǎng)頁來說,都有一定的特殊的結(jié)構(gòu)和層級(jí)關(guān)系,而且很多節(jié)點(diǎn)都有id或class來對(duì)作區(qū)分,所以我們借助于它們的結(jié)構(gòu)和屬性來提取不也是可以的嗎?

所以,這一節(jié)我們就介紹一個(gè)強(qiáng)大的解析工具,叫做 BeautiSoup,它就是借助網(wǎng)頁的結(jié)構(gòu)和屬性等特性來解析網(wǎng)頁的工具,有了它我們不用再去寫一些復(fù)雜的正則,只需要簡單的幾條語句就可以完成網(wǎng)頁中某個(gè)元素的提取。

廢話不多說,接下來我們就來感受一下 BeautifulSoup 的強(qiáng)大之處吧。

1. BeautifulSoup簡介

簡單來說,BeautifulSoup 就是 Python 的一個(gè) HTML 或 XML 的解析庫,我們可以用它來方便地從網(wǎng)頁中提取數(shù)據(jù),官方的解釋如下:

BeautifulSoup提供一些簡單的、Python式的函數(shù)用來處理導(dǎo)航、搜索、修改分析樹等功能。它是一個(gè)工具箱,通過解析文檔為用戶提供需要抓取的數(shù)據(jù),因?yàn)楹唵?,所以不需要多少代碼就可以寫出一個(gè)完整的應(yīng)用程序。 BeautifulSoup 自動(dòng)將輸入文檔轉(zhuǎn)換為 Unicode 編碼,輸出文檔轉(zhuǎn)換為 utf-8 編碼。你不需要考慮編碼方式,除非文檔沒有指定一個(gè)編碼方式,這時(shí)你僅僅需要說明一下原始編碼方式就可以了。 BeautifulSoup 已成為和 lxml、html6lib 一樣出色的 Python 解釋器,為用戶靈活地提供不同的解析策略或強(qiáng)勁的速度。

所以說,利用它我們可以省去很多繁瑣的提取工作,提高解析效率。

2. 準(zhǔn)備工作

在開始之前請(qǐng)確保已經(jīng)正確安裝好了 BeautifulSoup 和 LXML,如沒有安裝可以參考第一章的安裝過程。

3. 解析器

BeautifulSoup 在解析的時(shí)候?qū)嶋H上是依賴于解析器的,它除了支持 Python 標(biāo)準(zhǔn)庫中的 HTML 解析器,還支持一些第三方的解析器比如 LXML,下面我們對(duì) BeautifulSoup 支持的解析器及它們的一些優(yōu)缺點(diǎn)做一個(gè)簡單的對(duì)比。

解析器 使用方法 優(yōu)勢(shì) 劣勢(shì)
Python標(biāo)準(zhǔn)庫 BeautifulSoup(markup, "html.parser") Python的內(nèi)置標(biāo)準(zhǔn)庫、執(zhí)行速度適中 、文檔容錯(cuò)能力強(qiáng) Python 2.7.3 or 3.2.2)前的版本中 中文容錯(cuò)能力差
LXML HTML 解析器 BeautifulSoup(markup, "lxml") 速度快、文檔容錯(cuò)能力強(qiáng) 需要安裝C語言庫
LXML XML 解析器 BeautifulSoup(markup, "xml") 速度快、唯一支持XML的解析器 需要安裝C語言庫
html5lib BeautifulSoup(markup, "html5lib") 最好的容錯(cuò)性、以瀏覽器的方式解析文檔、生成 HTML5 格式的文檔 速度慢、不依賴外部擴(kuò)展

所以通過以上對(duì)比可以看出,LXML 這個(gè)解析器有解析 HTML 和 XML 的功能,而且速度快,容錯(cuò)能力強(qiáng),所以推薦使用這個(gè)解析器來進(jìn)行解析。

使用 LXML 這個(gè)解析器,在初始化 BeautifulSoup 的時(shí)候我們可以把第二個(gè)參數(shù)改為 lxml 即可,如下:

from bs4 import BeautifulSoup
soup = BeautifulSoup("

Hello

", "lxml") print(soup.p.string)

后面 BeautifulSoup 的用法實(shí)例也統(tǒng)一用這個(gè)解析器來演示。
4# . 基本使用

下面我們首先用一個(gè)實(shí)例來感受一下 BeautifulSoup 的基本使用:

html = """
The Dormouse"s story

The Dormouse"s story

Once upon a time there were three little sisters; and their names were , Lacie and Tillie; and they lived at the bottom of a well.

...

""" from bs4 import BeautifulSoup soup = BeautifulSoup(html, "lxml") print(soup.prettify()) print(soup.title.string)

運(yùn)行結(jié)果:


 
  
   The Dormouse"s story
  
 
 
  

The Dormouse"s story

Once upon a time there were three little sisters; and their names were , Lacie and Tillie ; and they lived at the bottom of a well.

...

The Dormouse"s story

首先我們聲明了一個(gè)變量 html,它是一個(gè) HTML 字符串,但是注意到,它并不是一個(gè)完整的 HTML 字符串,body 和 html 節(jié)點(diǎn)都沒有閉合,但是我們將它當(dāng)作第一個(gè)參數(shù)傳給 BeautifulSoup 對(duì)象,第二個(gè)參數(shù)傳入的是解析器的類型,在這里我們使用 lxml,這樣就完成了 BeaufulSoup 對(duì)象的初始化,將它賦值給 soup 這個(gè)變量。

那么接下來我們就可以通過調(diào)用 soup 的各個(gè)方法和屬性對(duì)這串 HTML代碼解析了。

我們首先調(diào)用了 prettify() 方法,這個(gè)方法可以把要解析的字符串以標(biāo)準(zhǔn)的縮進(jìn)格式輸出,在這里注意到輸出結(jié)果里面包含了 body 和 html 節(jié)點(diǎn),也就是說對(duì)于不標(biāo)準(zhǔn)的 HTML 字符串 BeautifulSoup 可以自動(dòng)更正格式,這一步實(shí)際上不是由 prettify() 方法做的,這個(gè)更正實(shí)際上在初始化 BeautifulSoup 時(shí)就完成了。

然后我們調(diào)用了 soup.title.string ,這個(gè)實(shí)際上是輸出了 HTML 中 title 節(jié)點(diǎn)的文本內(nèi)容。所以 soup.title 就可以選擇出 HTML 中的 title 節(jié)點(diǎn),再調(diào)用 string 屬性就可以得到里面的文本了,所以我們就可以通過簡單地調(diào)用幾個(gè)屬性就可以完成文本的提取了,是不是非常方便?

5. 節(jié)點(diǎn)選擇器

剛才我們選擇元素的時(shí)候直接通過調(diào)用節(jié)點(diǎn)的名稱就可以選擇節(jié)點(diǎn)元素了,然后再調(diào)用 string 屬性就可以得到節(jié)點(diǎn)內(nèi)的文本了,這種選擇方式速度非???,如果單個(gè)節(jié)點(diǎn)結(jié)構(gòu)話層次非常清晰,可以選用這種方式來解析。

選擇元素

下面我們?cè)儆靡粋€(gè)例子詳細(xì)說明一下它的選擇方法:

html = """
The Dormouse"s story

The Dormouse"s story

Once upon a time there were three little sisters; and their names were , Lacie and Tillie; and they lived at the bottom of a well.

...

""" from bs4 import BeautifulSoup soup = BeautifulSoup(html, "lxml") print(soup.title) print(type(soup.title)) print(soup.title.string) print(soup.head) print(soup.p)

運(yùn)行結(jié)果:

The Dormouse"s story

The Dormouse"s story
The Dormouse"s story

The Dormouse"s story

在這里我們依然選用了剛才的 HTML 代碼,我們首先打印輸出了 title 節(jié)點(diǎn)的選擇結(jié)果,輸出結(jié)果正是 title 節(jié)點(diǎn)加里面的文字內(nèi)容。接下來輸出了它的類型,是 bs4.element.Tag 類型,這是 BeautifulSoup 中的一個(gè)重要的數(shù)據(jù)結(jié)構(gòu),經(jīng)過選擇器選擇之后,選擇結(jié)果都是這種 Tag 類型,它具有一些屬性比如 string 屬性,調(diào)用 Tag 的 string 屬性,就可以得到節(jié)點(diǎn)的文本內(nèi)容了,所以接下來的輸出結(jié)果正是節(jié)點(diǎn)的文本內(nèi)容。

接下來我們又嘗試選擇了 head 節(jié)點(diǎn),結(jié)果也是節(jié)點(diǎn)加其內(nèi)部的所有內(nèi)容,再接下來選擇了 p 節(jié)點(diǎn),不過這次情況比較特殊,我們發(fā)現(xiàn)結(jié)果是第一個(gè) p 節(jié)點(diǎn)的內(nèi)容,后面的幾個(gè) p 節(jié)點(diǎn)并沒有選擇到,也就是說,當(dāng)有多個(gè)節(jié)點(diǎn)時(shí),這種選擇方式只會(huì)選擇到第一個(gè)匹配的節(jié)點(diǎn),其他的后面的節(jié)點(diǎn)都會(huì)忽略。

提取信息

在上面我們演示了調(diào)用 string 屬性來獲取文本的值,那我們要獲取節(jié)點(diǎn)屬性值怎么辦呢?獲取節(jié)點(diǎn)名怎么辦呢?下面我們來統(tǒng)一梳理一下信息的提取方式

獲取名稱

可以利用 name 屬性來獲取節(jié)點(diǎn)的名稱。還是以上面的文本為例,我們選取 title 節(jié)點(diǎn),然后調(diào)用 name 屬性就可以得到節(jié)點(diǎn)名稱。

print(soup.title.name)

運(yùn)行結(jié)果:

title
獲取屬性

每個(gè)節(jié)點(diǎn)可能有多個(gè)屬性,比如 id,class 等等,我們選擇到這個(gè)節(jié)點(diǎn)元素之后,可以調(diào)用 attrs 獲取所有屬性。

print(soup.p.attrs)
print(soup.p.attrs["name"])

運(yùn)行結(jié)果:

{"class": ["title"], "name": "dromouse"}
dromouse

可以看到 attrs 的返回結(jié)果是字典形式,把選擇的節(jié)點(diǎn)的所有屬性和屬性值組合成一個(gè)字典,接下來如果要獲取 name 屬性,就相當(dāng)于從字典中獲取某個(gè)鍵值,只需要用中括號(hào)加屬性名稱就可以得到結(jié)果了,比如獲取 name 屬性就可以通過 attrs["name"] 得到相應(yīng)的屬性值。

其實(shí)這樣的寫法還有點(diǎn)繁瑣,還有一種更簡單的獲取方式,我們可以不用寫 attrs,直接節(jié)點(diǎn)元素后面加中括號(hào),傳入屬性名就可以達(dá)到屬性值了,樣例如下:

print(soup.p["name"])
print(soup.p["class"])

運(yùn)行結(jié)果:

dromouse
["title"]

在這里注意到有的返回結(jié)果是字符串,有的返回結(jié)果是字符串組成的列表。比如 name 屬性的值是唯一的,返回的結(jié)果就是單個(gè)字符串,而對(duì)于 class,一個(gè)節(jié)點(diǎn)元素可能由多個(gè) class,所以返回的是列表,所以在實(shí)際處理過程中要注意判斷類型。

獲取內(nèi)容

可以利用 string 屬性獲取節(jié)點(diǎn)元素包含的文本內(nèi)容,比如上面的文本我們獲取第一個(gè) p 節(jié)點(diǎn)的文本:

print(soup.p.string)

運(yùn)行結(jié)果:

The Dormouse"s story

再次注意一下這里選擇到的 p 節(jié)點(diǎn)是第一個(gè) p 節(jié)點(diǎn),獲取的文本也就是第一個(gè) p 節(jié)點(diǎn)里面的文本。

嵌套選擇

在上面的例子中我們知道每一個(gè)返回結(jié)果都是 bs4.element.Tag 類型,它同樣可以繼續(xù)調(diào)用節(jié)點(diǎn)進(jìn)行下一步的選擇,比如我們獲取了 head 節(jié)點(diǎn)元素,我們可以繼續(xù)調(diào)用 head 來選取其內(nèi)部的 head 節(jié)點(diǎn)元素。

html = """
The Dormouse"s story

"""
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "lxml")
print(soup.head.title)
print(type(soup.head.title))
print(soup.head.title.string)

運(yùn)行結(jié)果:

The Dormouse"s story

The Dormouse"s story

第一行結(jié)果是我們調(diào)用了 head 之后再次調(diào)用了 title 來選擇的 title 節(jié)點(diǎn)元素,然后我們緊接著打印輸出了它的類型,可以看到它仍然是 bs4.element.Tag 類型,也就是說我們?cè)?Tag 類型的基礎(chǔ)上再次選擇得到的依然還是 Tag 類型,每次返回的結(jié)果都相同,所以這樣我們就可以這樣做嵌套的選擇了。

最后輸出了一下它的 string 屬性,也就是節(jié)點(diǎn)里的文本內(nèi)容。

關(guān)聯(lián)選擇

我們?cè)谧鲞x擇的時(shí)候有時(shí)候不能做到一步就可以選擇到想要的節(jié)點(diǎn)元素,有時(shí)候在選擇的時(shí)候需要先選中某一個(gè)節(jié)點(diǎn)元素,然后以它為基準(zhǔn)再選擇它的子節(jié)點(diǎn)、父節(jié)點(diǎn)、兄弟節(jié)點(diǎn)等等。所以在這里我們就介紹下如何來選擇這些節(jié)點(diǎn)元素。

子節(jié)點(diǎn)和子孫節(jié)點(diǎn)

選取到了一個(gè)節(jié)點(diǎn)元素之后,如果想要獲取它的直接子節(jié)點(diǎn)可以調(diào)用 contents 屬性,我們用一個(gè)實(shí)例來感受一下:

print(soup.p.contents)

運(yùn)行結(jié)果:

[The Dormouse"s story]

contents 屬性得到的結(jié)果是直接子節(jié)點(diǎn)的列表。

同樣地我們可以調(diào)用 children 屬性,得到相應(yīng)的結(jié)果:

print(soup.p.children)
for i,child in enumerate(soup.p.children):
    print(child)

運(yùn)行結(jié)果:


The Dormouse"s story

還是同樣的 HTML 文本,在這里我們調(diào)用了 children 屬性來進(jìn)行選擇,返回結(jié)果可以看到是生成器類型,所以接下來我們用 for 循環(huán)輸出了一下相應(yīng)的內(nèi)容,內(nèi)容其實(shí)是一樣的,只不過 children 返回的是生成器類型,而 contents 返回的是列表類型。

如果我們要得到所有的子孫節(jié)點(diǎn)的話可以調(diào)用 descendants 屬性:

print(soup.p.descendants)
for i,child in enumerate(soup.p.descendants):
    print(child)

運(yùn)行結(jié)果:


The Dormouse"s story
The Dormouse"s story

返回結(jié)果還是生成器,遍歷輸出一下可以看到descendants 會(huì)遞歸地查詢所有子節(jié)點(diǎn),得到的是所有的子孫節(jié)點(diǎn)。

父節(jié)點(diǎn)和祖先節(jié)點(diǎn)

如果要獲取某個(gè)節(jié)點(diǎn)元素的父節(jié)點(diǎn),可以調(diào)用 parent 屬性:

html = """

    
        The Dormouse"s story
    
    
        

Once upon a time there were three little sisters; and their names were Elsie

...

""" from bs4 import BeautifulSoup soup = BeautifulSoup(html, "lxml") print(soup.a.parent)

運(yùn)行結(jié)果:

Once upon a time there were three little sisters; and their names were Elsie

在這里我們選擇的是第一個(gè) a 節(jié)點(diǎn)的父節(jié)點(diǎn)元素,很明顯它的父節(jié)點(diǎn)是 p 節(jié)點(diǎn),輸出結(jié)果便是 p 節(jié)點(diǎn)及其內(nèi)部的內(nèi)容。

注意到這里輸出的僅僅是 a 節(jié)點(diǎn)的直接父節(jié)點(diǎn),而沒有再向外尋找父節(jié)點(diǎn)的祖先節(jié)點(diǎn),如果我們要想獲取所有的祖先節(jié)點(diǎn),可以調(diào)用 parents 屬性:

html = """

    
        

Elsie

""" from bs4 import BeautifulSoup soup = BeautifulSoup(html, "lxml") print(type(soup.a.parents)) print(list(enumerate(soup.a.parents)))

運(yùn)行結(jié)果:


[(0, 

Elsie

), (1,

Elsie

), (2,

Elsie

), (3,

Elsie

)]

返回結(jié)果是一個(gè)生成器類型,我們?cè)谶@里用列表輸出了它的索引和內(nèi)容,可以發(fā)現(xiàn)列表中的元素就是 a 節(jié)點(diǎn)的祖先節(jié)點(diǎn)。

兄弟節(jié)點(diǎn)

上面說明了子節(jié)點(diǎn)和父節(jié)點(diǎn)的獲取方式,如果要獲取同級(jí)的節(jié)點(diǎn)也就是兄弟節(jié)點(diǎn)應(yīng)該怎么辦?我們先用一個(gè)實(shí)例來感受一下:

html = """

    
        

Once upon a time there were three little sisters; and their names were Elsie Hello Lacie and Tillie and they lived at the bottom of a well.

""" from bs4 import BeautifulSoup soup = BeautifulSoup(html, "lxml") print("Next Sibling", soup.a.next_sibling) print("Prev Sibling", soup.a.previous_sibling) print("Next Siblings", list(enumerate(soup.a.next_siblings))) print("Prev Siblings", list(enumerate(soup.a.previous_siblings)))

運(yùn)行結(jié)果:

Next Sibling 
            Hello
            
Prev Sibling 
            Once upon a time there were three little sisters; and their names were
            
Next Siblings [(0, "
            Hello
            "), (1, Lacie), (2, " 
            and
            "), (3, Tillie), (4, "
            and they lived at the bottom of a well.
        ")]
Prev Siblings [(0, "
            Once upon a time there were three little sisters; and their names were
            ")]

可以看到在這里我們調(diào)用了四個(gè)不同的屬性,next_sibling 和 previous_sibling 分別可以獲取節(jié)點(diǎn)的下一個(gè)和上一個(gè)兄弟元素,next_siblings 和 previous_siblings 則分別返回所有前面和后面的兄弟節(jié)點(diǎn)的生成器。

提取信息

在上面我們講解了關(guān)聯(lián)元素節(jié)點(diǎn)的選擇方法,如果我們想要獲取它們的一些信息,比如文本、屬性等等也是同樣的方法。

html = """

    
        

Once upon a time there were three little sisters; and their names were BobLacie

""" from bs4 import BeautifulSoup soup = BeautifulSoup(html, "lxml") print("Next Sibling:") print(type(soup.a.next_sibling)) print(soup.a.next_sibling) print(soup.a.next_sibling.string) print("Parent:") print(type(soup.a.parents)) print(list(soup.a.parents)[0]) print(list(soup.a.parents)[0].attrs["class"])

運(yùn)行結(jié)果:

Next Sibling:

Lacie
Lacie
Parent:

Once upon a time there were three little sisters; and their names were BobLacie

["story"]

如果返回結(jié)果是單個(gè)節(jié)點(diǎn),那么可以直接調(diào)用 string、attrs 等屬性來獲得其文本和屬性,如果返回結(jié)果是多個(gè)節(jié)點(diǎn)的生成器,則可以轉(zhuǎn)為列表后取出某個(gè)元素,然后再調(diào)用 string、attrs 等屬性來獲取其對(duì)應(yīng)節(jié)點(diǎn)等文本和屬性。

6. 方法選擇器

前面我們所講的選擇方法都是通過屬性來選擇元素的,這種選擇方法非??欤侨绻M(jìn)行比較復(fù)雜的選擇的話則會(huì)比較繁瑣,不夠靈活。所以 BeautifulSoup 還為我們提供了一些查詢的方法,比如 find_all()、find() 等方法,我們可以調(diào)用方法然后傳入相應(yīng)等參數(shù)就可以靈活地進(jìn)行查詢了。

最常用的查詢方法莫過于 find_all() 和 find() 了,下面我們對(duì)它們的用法進(jìn)行詳細(xì)的介紹。

find_all()

find_all,顧名思義,就是查詢所有符合條件的元素,可以給它傳入一些屬性或文本來得到符合條件的元素,功能十分強(qiáng)大。

它的API如下:

find_all(name , attrs , recursive , text , **kwargs)
name

我們可以根據(jù)節(jié)點(diǎn)名來查詢?cè)?,下面我們用一個(gè)實(shí)例來感受一下:

html="""

Hello

  • Foo
  • Bar
  • Jay
  • Foo
  • Bar
""" from bs4 import BeautifulSoup soup = BeautifulSoup(html, "lxml") print(soup.find_all(name="ul")) print(type(soup.find_all(name="ul")[0]))

運(yùn)行結(jié)果:

[
  • Foo
  • Bar
  • Jay
,
  • Foo
  • Bar
]

在這里我們調(diào)用了 find_all() 方法,傳入了一個(gè) name 參數(shù),參數(shù)值為 ul,也就是說我們想要查詢所有 ul 節(jié)點(diǎn),返回結(jié)果是列表類型,長度為 2,每個(gè)元素依然都是 bs4.element.Tag 類型。

因?yàn)槎际?Tag 類型,所以我們依然可以進(jìn)行嵌套查詢,還是同樣的文本,在這里我們查詢出所有 ul 節(jié)點(diǎn)后再繼續(xù)查詢其內(nèi)部的 li 節(jié)點(diǎn)。

for ul in soup.find_all(name="ul"):
    print(ul.find_all(name="li"))

運(yùn)行結(jié)果:

[
  • Foo
  • ,
  • Bar
  • ,
  • Jay
  • ] [
  • Foo
  • ,
  • Bar
  • ]

    返回結(jié)果是列表類型,列表中的每個(gè)元素依然還是 Tag 類型。

    接下來我們就可以遍歷每個(gè) li 獲取它的文本了。

    for ul in soup.find_all(name="ul"):
        print(ul.find_all(name="li"))
        for li in ul.find_all(name="li"):
            print(li.string)

    運(yùn)行結(jié)果:

    [
  • Foo
  • ,
  • Bar
  • ,
  • Jay
  • ] Foo Bar Jay [
  • Foo
  • ,
  • Bar
  • ] Foo Bar
    attrs

    除了根據(jù)節(jié)點(diǎn)名查詢,我們也可以傳入一些屬性來進(jìn)行查詢,我們用一個(gè)實(shí)例感受一下:

    html="""
    

    Hello

    • Foo
    • Bar
    • Jay
    • Foo
    • Bar
    """ from bs4 import BeautifulSoup soup = BeautifulSoup(html, "lxml") print(soup.find_all(attrs={"id": "list-1"})) print(soup.find_all(attrs={"name": "elements"}))

    運(yùn)行結(jié)果:

    [
    • Foo
    • Bar
    • Jay
    ] [
    • Foo
    • Bar
    • Jay
    ]

    在這里我們查詢的時(shí)候傳入的是 attrs 參數(shù),參數(shù)的類型是字典類型,比如我們要查詢 id 為 list-1 的節(jié)點(diǎn),那就可以傳入attrs={"id": "list-1"} 的查詢條件,得到的結(jié)果是列表形式,包含的內(nèi)容就是符合 id 為 list-1 的所有節(jié)點(diǎn),上面的例子中符合條件的元素個(gè)數(shù)是 1,所以結(jié)果是長度為 1 的列表。

    對(duì)于一些常用的屬性比如 id、class 等,我們可以不用 attrs 來傳遞,比如我們要查詢 id 為 list-1 的節(jié)點(diǎn),我們可以直接傳入 id 這個(gè)參數(shù),還是上面的文本,我們換一種方式來查詢。

    from bs4 import BeautifulSoup
    soup = BeautifulSoup(html, "lxml")
    print(soup.find_all(id="list-1"))
    print(soup.find_all(class_="element"))

    運(yùn)行結(jié)果:

    [
    • Foo
    • Bar
    • Jay
    ] [
  • Foo
  • ,
  • Bar
  • ,
  • Jay
  • ,
  • Foo
  • ,
  • Bar
  • ]

    在這里我們直接傳入 id="list-1" 就可以查詢 id 為 list-1 的節(jié)點(diǎn)元素了。而對(duì)于 class 來說,由于 class 在 python 里是一個(gè)關(guān)鍵字,所以在這里后面需要加一個(gè)下劃線,class_="element",返回的結(jié)果依然還是 Tag 組成的列表。

    text

    text 參數(shù)可以用來匹配節(jié)點(diǎn)的文本,傳入的形式可以是字符串,可以是正則表達(dá)式對(duì)象,我們用一個(gè)實(shí)例來感受一下:

    import re
    html="""
    
    """
    from bs4 import BeautifulSoup
    soup = BeautifulSoup(html, "lxml")
    print(soup.find_all(text=re.compile("link")))

    運(yùn)行結(jié)果:

    ["Hello, this is a link", "Hello, this is a link, too"]

    在這里有兩個(gè) a 節(jié)點(diǎn),其內(nèi)部包含有文本信息,在這里我們調(diào)用 find_all() 方法傳入 text 參數(shù),參數(shù)為正則表達(dá)式對(duì)象,結(jié)果會(huì)返回所有匹配正則表達(dá)式的節(jié)點(diǎn)文本組成的列表。

    find()

    除了 find_all() 方法,還有 find() 方法,只不過 find() 方法返回的是單個(gè)元素,也就是第一個(gè)匹配的元素,而 find_all() 返回的是所有匹配的元素組成的列表。

    html="""
    

    Hello

    • Foo
    • Bar
    • Jay
    • Foo
    • Bar
    """ from bs4 import BeautifulSoup soup = BeautifulSoup(html, "lxml") print(soup.find(name="ul")) print(type(soup.find(name="ul"))) print(soup.find(class_="list"))

    運(yùn)行結(jié)果:

    • Foo
    • Bar
    • Jay
    • Foo
    • Bar
    • Jay

    返回結(jié)果不再是列表形式,而是第一個(gè)匹配的節(jié)點(diǎn)元素,類型依然是 Tag 類型。

    另外還有許多的查詢方法,用法與前面介紹的 find_all()、find() 方法完全相同,只不過查詢范圍不同,在此做一下簡單的說明。

    find_parents() find_parent()

    find_parents() 返回所有祖先節(jié)點(diǎn),find_parent() 返回直接父節(jié)點(diǎn)。

    find_next_siblings() find_next_sibling()

    find_next_siblings() 返回后面所有兄弟節(jié)點(diǎn),find_next_sibling() 返回后面第一個(gè)兄弟節(jié)點(diǎn)。

    find_previous_siblings() find_previous_sibling()

    find_previous_siblings() 返回前面所有兄弟節(jié)點(diǎn),find_previous_sibling() 返回前面第一個(gè)兄弟節(jié)點(diǎn)。

    find_all_next() find_next()

    find_all_next() 返回節(jié)點(diǎn)后所有符合條件的節(jié)點(diǎn), find_next() 返回第一個(gè)符合條件的節(jié)點(diǎn)。

    find_all_previous() 和 find_previous()

    find_all_previous() 返回節(jié)點(diǎn)后所有符合條件的節(jié)點(diǎn), find_previous() 返回第一個(gè)符合條件的節(jié)點(diǎn)

    7. CSS選擇器

    BeautifulSoup 還提供了另外一種選擇器,那就是 CSS 選擇器,如果對(duì) Web 開發(fā)熟悉對(duì)話,CSS 選擇器肯定也不陌生,如果不熟悉的話,可以看一下:http://www.w3school.com.cn/cs...。

    使用 CSS 選擇器,只需要調(diào)用 select() 方法,傳入相應(yīng)的 CSS 選擇器即可,我們用一個(gè)實(shí)例來感受一下:

    html="""
    

    Hello

    • Foo
    • Bar
    • Jay
    • Foo
    • Bar
    """ from bs4 import BeautifulSoup soup = BeautifulSoup(html, "lxml") print(soup.select(".panel .panel-heading")) print(soup.select("ul li")) print(soup.select("#list-2 .element")) print(type(soup.select("ul")[0]))

    運(yùn)行結(jié)果:

    [

    Hello

    ] [
  • Foo
  • ,
  • Bar
  • ,
  • Jay
  • ,
  • Foo
  • ,
  • Bar
  • ] [
  • Foo
  • ,
  • Bar
  • ]

    在這里我們用了三次 CSS 選擇器,返回的結(jié)果均是符合 CSS 選擇器的節(jié)點(diǎn)組成的列表。例如 select("ul li") 則是選擇所有 ul 節(jié)點(diǎn)下面的所有 li 節(jié)點(diǎn),結(jié)果便是所有的 li 節(jié)點(diǎn)組成的列表。

    最后一句我們打印輸出了列表中元素的類型,可以看到類型依然是 Tag 類型。

    嵌套選擇

    select() 方法同樣支持嵌套選擇,例如我們先選擇所有 ul 節(jié)點(diǎn),再遍歷每個(gè) ul 節(jié)點(diǎn)選擇其 li 節(jié)點(diǎn),樣例如下:

    from bs4 import BeautifulSoup
    soup = BeautifulSoup(html, "lxml")
    for ul in soup.select("ul"):
        print(ul.select("li"))

    運(yùn)行結(jié)果:

    [
  • Foo
  • ,
  • Bar
  • ,
  • Jay
  • ] [
  • Foo
  • ,
  • Bar
  • ]

    可以看到正常輸出了遍歷每個(gè) ul 節(jié)點(diǎn)之后,其下的所有 li 節(jié)點(diǎn)組成的列表。

    獲取屬性

    我們知道節(jié)點(diǎn)類型是 Tag 類型,所以獲取屬性還是可以用原來的方法獲取,仍然是上面的 HTML 文本,我們?cè)谶@里嘗試獲取每個(gè) ul 節(jié)點(diǎn)的 id 屬性。

    from bs4 import BeautifulSoup
    soup = BeautifulSoup(html, "lxml")
    for ul in soup.select("ul"):
        print(ul["id"])
        print(ul.attrs["id"])

    運(yùn)行結(jié)果:

    list-1
    list-1
    list-2
    list-2

    可以看到直接傳入中括號(hào)和屬性名和通過 attrs 屬性獲取屬性值都是可以成功的。

    獲取文本

    那么獲取文本當(dāng)然也可以用前面所講的 string 屬性,還有一個(gè)方法那就是 get_text(),同樣可以獲取文本值。

    from bs4 import BeautifulSoup
    soup = BeautifulSoup(html, "lxml")
    for li in soup.select("li"):
        print("Get Text:", li.get_text())
        print("String:", li.string)

    運(yùn)行結(jié)果:

    Get Text: Foo
    String: Foo
    Get Text: Bar
    String: Bar
    Get Text: Jay
    String: Jay
    Get Text: Foo
    String: Foo
    Get Text: Bar
    String: Bar

    二者的效果是完全一致的,都可以獲取到節(jié)點(diǎn)的文本值。

    8. 結(jié)語

    到此 BeautifulSoup 的使用介紹基本就結(jié)束了,最后做一下簡單的總結(jié):

    推薦使用 LXML 解析庫,必要時(shí)使用 html.parser。

    節(jié)點(diǎn)選擇篩選功能弱但是速度快。

    建議使用 find()、find_all() 查詢匹配單個(gè)結(jié)果或者多個(gè)結(jié)果。

    如果對(duì) CSS 選擇器熟悉的話可以使用 select() 選擇法。

    上一篇文章:Python3網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)---28、解析庫的使用:XPath
    下一篇文章:Python3網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)---30、解析庫的使用:PyQuery

    文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

    轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/44083.html

    相關(guān)文章

    • Python3網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)---4、數(shù)據(jù)庫的安裝:MySQL、MongoDB、Redis

      摘要:運(yùn)行結(jié)果如果運(yùn)行結(jié)果一致則證明安裝成功。上一篇文章網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)請(qǐng)求庫安裝下一篇文章網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)數(shù)據(jù)庫的安裝 上一篇文章:Python3網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)---2、請(qǐng)求庫安裝:GeckoDriver、PhantomJS、Aiohttp下一篇文章:Python3網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)---數(shù)據(jù)庫的安裝:MySQL、MongoDB、Redis 抓取下網(wǎng)頁代碼之后,下一步就是從網(wǎng)頁中提取信息,提取信息的方式有...

      xbynet 評(píng)論0 收藏0
    • Python3網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)---30、解析庫的使用:PyQuery

      摘要:父節(jié)點(diǎn)我們可以用方法來獲取某個(gè)節(jié)點(diǎn)的父節(jié)點(diǎn),我們用一個(gè)實(shí)例來感受一下運(yùn)行結(jié)果在這里我們首先用選取了為的節(jié)點(diǎn),然后調(diào)用了方法,得到其父節(jié)點(diǎn),類型依然是類型。 上一篇文章:Python3網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)---29、解析庫的使用:BeautifulSoup下一篇文章:Python3網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)---31、數(shù)據(jù)存儲(chǔ):文件存儲(chǔ) 在上一節(jié)我們介紹了 BeautifulSoup 的使用,它是一個(gè)非常強(qiáng)...

      IntMain 評(píng)論0 收藏0
    • Python3網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)---4、數(shù)據(jù)庫的安裝:MySQL、MongoDB、Redis

      摘要:的安裝是一個(gè)輕量級(jí)的關(guān)系型數(shù)據(jù)庫,以表的形式來存儲(chǔ)數(shù)據(jù),本節(jié)我們來了解下它的安裝方式。相關(guān)鏈接官方網(wǎng)站下載地址中文教程下的安裝推薦使用安裝,執(zhí)行命令即可。上一篇文章網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)解析庫的安裝下一篇文章網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)存儲(chǔ)庫的安裝 上一篇文章:Python3網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)---3、解析庫的安裝:LXML、BeautifulSoup、PyQuery、Tesserocr下一篇文章:Python3網(wǎng)絡(luò)...

      winterdawn 評(píng)論0 收藏0
    • Python3網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)---2、請(qǐng)求庫安裝:GeckoDriver、PhantomJS、Aioh

      摘要:上一篇文章網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)請(qǐng)求庫安裝下一篇文章網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)解析庫的安裝的安裝在上一節(jié)我們了解了的配置方法,配置完成之后我們便可以用來驅(qū)動(dòng)瀏覽器來做相應(yīng)網(wǎng)頁的抓取。上一篇文章網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)請(qǐng)求庫安裝下一篇文章網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)解析庫的安裝 上一篇文章:Python3網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)---1、請(qǐng)求庫安裝:Requests、Selenium、ChromeDriver下一篇文章:Python3網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)--...

      Cristalven 評(píng)論0 收藏0
    • Python3網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)---28、解析庫的使用:XPath

      摘要:上一篇文章網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)與正則表達(dá)式抓取貓眼電影排行下一篇文章網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)解析庫的使用上一節(jié)我們實(shí)現(xiàn)了一個(gè)最基本的爬蟲,但提取頁面信息時(shí)我們使用的是正則表達(dá)式,用過之后我們會(huì)發(fā)現(xiàn)構(gòu)造一個(gè)正則表達(dá)式還是比較的繁瑣的,而且萬一有一點(diǎn)地 上一篇文章:Python3網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)---27、Requests與正則表達(dá)式抓取貓眼電影排行下一篇文章:Python3網(wǎng)絡(luò)爬蟲實(shí)戰(zhàn)---29、解析庫的使用:...

      abson 評(píng)論0 收藏0

    發(fā)表評(píng)論

    0條評(píng)論

    最新活動(dòng)
    閱讀需要支付1元查看
    <