国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
比正則表達(dá)式好用,用BeautifulSoup來(lái)煲美味的湯

  許多人喜歡在介紹正則表達(dá)式以后才來(lái)介紹本篇BeautifulSoup的用法,但是我覺(jué)得BeautifulSoup比正則表達(dá)式好用,而且容易上手,非常適合小白入門爬蟲,并且可以利用學(xué)到的這個(gè)知識(shí)立即去爬取自己想爬的網(wǎng)站,成就感滿滿的。好了話不多說(shuō),立即進(jìn)入今天的介紹吧。

你可能會(huì)問(wèn)BeautifulSoup:美味的湯?這個(gè)東西能干嘛?為什么起這個(gè)名字呢?先來(lái)看一下官方的介紹。

BeautifulSoup: We called him Tortoise because he taught us

翻譯過(guò)來(lái)就是:我們叫他烏龜因?yàn)樗塘宋覀儭J遣皇沁€是懵圈,沒(méi)辦法外國(guó)人起名字就是這么隨意。誰(shuí)能知道那么厲害的Java竟然是開發(fā)者在樓下覺(jué)得味道不錯(cuò)的一種咖啡的名字呢,哈哈哈哈。算了,我們不糾結(jié)這個(gè)問(wèn)題了,我們還是開始介紹它的安裝和使用吧。話不多說(shuō),走你!

BeautifulSoup的安裝

目前BeautifulSoup已經(jīng)更新到了BeautifulSoup4,在Python中你只需要以bs4模塊引入即可。小編我用的Python的版本是3.6.4,所以可以使用pip3 install bs4 來(lái)進(jìn)行安裝,當(dāng)然了你也可以去官方下載到本地然后再進(jìn)行安裝:鏈接:https://www.crummy.com/software/BeautifulSoup/,具體的安裝我這里就不介紹了,不懂的可以自行百度。

說(shuō)到這里,你可能還是不知道BeautifulSoup是干嘛的,說(shuō)白了它其實(shí)就是Python的一個(gè)HTML或者XML的解析庫(kù),但是它在解析的時(shí)候?qū)嶋H上還是依賴解析器的,下面就列舉一些BeautifulSoup支持的解析器:

解析器

使用方法及特點(diǎn)

Python標(biāo)準(zhǔn)庫(kù)

BeautifulSoup(markup, "html.parser"),速度適中,容錯(cuò)能力較弱

lxml HTML解析器

BeautifulSoup(markup, "lxml"),速度快,文檔容錯(cuò)能力強(qiáng)

lxml XML解析器

BeautifulSoup(markup, ["lxml", "xml"])BeautifulSoup(markup, "xml"),速度快,唯一支持XM鏈的解析器

html5lib

BeautifulSoup(markup, "html5lib"),速度慢、不依賴外部擴(kuò)展

通過(guò)以上對(duì)比可以看出, lxml解析器有解析 HTML 和 XML 的功能, 而且速度快, 容錯(cuò)能力強(qiáng)所以推薦使用它。

接下來(lái)教你如何使用BeautifulSoup和lxml進(jìn)行數(shù)據(jù)的提取。在此之前,我們需要?jiǎng)?chuàng)建一個(gè)BeautifulSoup的文檔對(duì)象,依據(jù)不同需要可以傳入“字符串”或者“一個(gè)文件句柄”。

當(dāng)傳入“字符串”時(shí),

soup = BeautifulSoup(html_doc,"lxml")

當(dāng)傳入“文件句柄”并打開一個(gè)本地文件時(shí),

soup = BeautifulSoup(open("index.html"),"lxml")

接下來(lái)便是BeautifulSoup的對(duì)象種類的介紹,它有4種類型,下面我們分別進(jìn)行說(shuō)明。

BeautifulSoup的對(duì)象種類

Beautiful Soup實(shí)質(zhì)是將復(fù)雜的HTML文檔轉(zhuǎn)換成一個(gè)復(fù)雜的樹形結(jié)構(gòu)(因?yàn)镠TML本身就是DOM),然后每個(gè)節(jié)點(diǎn)都是Python對(duì)象,通過(guò)分析可以把所有對(duì)象分成4種類型:Tag、NavigableString、BeautifulSoup、Comment。

1、<Tag>

Tag其實(shí)就是html或者xml中的標(biāo)簽,BeautifulSoup會(huì)通過(guò)一定的方法自動(dòng)尋找你想要的指定標(biāo)簽??聪旅孢@個(gè)例子:

soup=BeautifulSoup('<p class="good">Excelent boy</p>')

tag = soup.p

type(tag)

>>> <class 'bs4.element.Tag'>

其實(shí)Tag標(biāo)簽也是有屬性的,name和attributes就是非常重要的兩個(gè)屬性。

Name

Name就是標(biāo)簽tag的名字,一個(gè)標(biāo)簽的名字是唯一的,我們直接調(diào)用tag.name即可簡(jiǎn)單獲取tag的名字。

tag.name

>>> 'p'

Attributes

我們知道一個(gè)標(biāo)簽下面可能會(huì)有很多屬性,比如上面那個(gè)標(biāo)簽p有class屬性,屬性值為good,那么我們?nèi)绾潍@取這個(gè)屬性值呢?我們可以仿照Python中操作字典那樣通過(guò)key來(lái)獲取value的值的方法,來(lái)獲取tag的每個(gè)屬性對(duì)應(yīng)的值:

tag['class']

>>> 'good'

當(dāng)然你也是可以通過(guò)tag.attrs來(lái)獲取所有屬性(采用tag.attrs['屬性名稱']獲取指定屬性值),比如:

tag.attrs

>>> {'class': 'good'}

tag.attrs['class']

>>> 'good'

2、<NavigableString>

NavigableString其實(shí)就是可以遍歷的字符串(標(biāo)簽內(nèi)包括的字符串),在BeautifulSoup中可以采用.string的方式來(lái)直接獲取標(biāo)簽內(nèi)的字符串。

tag.string

>>> ''Excelent boy'

是不是非常簡(jiǎn)單。不過(guò)要說(shuō)明的是,tag中包含的字符串是不能編輯的,但是可以替換:

tag.string.replace_with("Bad boy")

tag

>>><blockquote>Bad boy</blockquote>

3、<BeautifulSoup>

BeautifulSoup對(duì)象其實(shí)它表示的是一個(gè)文檔的全部?jī)?nèi)容,不過(guò)大部分情況下,我們都是把它當(dāng)作Tag對(duì)象來(lái)使用的。例如:

soup.name

>>> '[document]'

但實(shí)際上BeautifulSoup對(duì)象不是一個(gè)真正的tag,前面說(shuō)了,tag有2個(gè)重要的屬性name和attributes,它是沒(méi)有的。但是卻可以查看它的name屬性,如上面采用soup.name方式獲取的“[document]”,我們可以理解為“[document]”是BeautifulSoup對(duì)象的特殊屬性名字。

4、<Comment>

Comment就是注釋,它是一個(gè)特殊類型的NavigableString對(duì)象,為什么這么說(shuō)呢,因?yàn)槲覀兛梢灾苯硬捎妙愃朴贜avigableString對(duì)象獲取字符串的方式來(lái)獲取注釋文本,看下面的例子你就明白了:

web_data = "<p><!--hello, everybody. Welcome to the world for python--></p>"

soup = BeautifulSoup(web_data)

comment = soup.p.string

type(comment)

>>> <class 'bs4.element.Comment'>

comment

>>> ''hello, everybody. Welcome to the world for python'

是不是和NavigableString的使用非常相似,我們這里使用 p.string 對(duì)標(biāo)簽內(nèi)的字符串進(jìn)行提取。但是這里有一個(gè)疑問(wèn),就是我們通過(guò)這種方式可以得到字符串,但是如果我們獲取了字符串,我們反過(guò)來(lái)是不知道這個(gè)字符串是Comment注釋,還是正常的標(biāo)簽內(nèi)的文本。所以我們?cè)谂廊?shù)據(jù)的時(shí)候需要進(jìn)行判斷,如果是Comment對(duì)象,我們就不爬了,直接跳過(guò):

if type(soup.p.string)==bs4.element.Comment:

continue;

說(shuō)完了4種對(duì)象類型,接下來(lái)說(shuō)一下BeautifulSoup如何對(duì)文檔樹進(jìn)行遍歷,從而找到我們想要的數(shù)據(jù)。

BeautifulSoup遍歷文檔樹

為了更好的介紹這些功能,我采用官方的例子進(jìn)行說(shuō)明:這段例子引自《愛麗絲漫游記》。

web_data =

"""

<html><head><title>The Dormouse's story</title></head><body>

<p class="title"><b>The Dormouse's story</b></p><p class="story">Once upon a time there were three little sisters; and their names were<a class="sister" id="link1">Elsie</a>,<a class="sister" id="link2">Lacie</a>and<a class="sister" id="link3">Tillie</a>;and they lived at the bottom of a well.</p><p class="story">...</p>

"""

我們以本體為起點(diǎn),先介紹子節(jié)點(diǎn),子孫節(jié)點(diǎn),再介紹父節(jié)點(diǎn),祖宗節(jié)點(diǎn),兄弟節(jié)點(diǎn)等信息。

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

子節(jié)點(diǎn)有就是當(dāng)前本體的下延,當(dāng)然就包括直接下延(子節(jié)點(diǎn))和間接下延了(子孫節(jié)點(diǎn)) ,首先介紹如何返回所有的子節(jié)點(diǎn),將介紹.contents.children 的用法。

contents

contents可以將標(biāo)簽所有的子節(jié)點(diǎn)以列表形式返回。

# <head><title>The Dormouse's story</title></head>

print(soup.head.contents)

>>> [title>The Dormouse's story</title>]

是不是很簡(jiǎn)單,當(dāng)然你也可以使用soup.title同樣能實(shí)現(xiàn)這個(gè)功能,但是你想過(guò)沒(méi),當(dāng)文檔結(jié)構(gòu)復(fù)雜的時(shí)候,比方說(shuō)不止一個(gè)title的時(shí)候,你還采用soup.title這種方式是不是太慢了,你需要區(qū)分那些title的不同,還需要全部輸出,用contents直接一步完事,超級(jí)easy。如果你不相信可以采用body這個(gè)標(biāo)簽來(lái)進(jìn)行測(cè)試:

print(soup.body.contents)

>>>

['\n', <p class="title"><b>The Dormouse's story</b></p>, '\n', <p class="story">Once upon a time there were three little sisters; and their names were

<a class="sister" id="link1">Elsie</a>,

<a class="sister" id="link2">Lacie</a>

and<a class="sister" id="link3">Tillie</a>;

and they lived at the bottom of a well.</p>, '\n', <p class="story">...</p>, '\n']

你會(huì)發(fā)現(xiàn).contents返回的是一個(gè)列表,而且列表中有很多“\n”,這是因?yàn)樗?strong>空格也包括進(jìn)去了,所以如果我們需要提取其中的文本內(nèi)容,我們還需要采用split()或者sub()來(lái)去掉空格,這部分后面實(shí)戰(zhàn)部分有介紹。

children

我們也可以通過(guò) .chidren 的方式獲取所有的子節(jié)點(diǎn),與之不同的是 .chidren返回的是一個(gè)生成器(generator),而不是一個(gè)列表。

print(soup.body.children)

>>> <list_iterator object at 0x00000000035B4550>

對(duì)于生成器,我們可以先采用list(),轉(zhuǎn)化為列表,再進(jìn)行遍歷:

for child in list(soup.body.children): print(child)

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

說(shuō)完了子節(jié)點(diǎn),下面我們說(shuō)一下子孫節(jié)點(diǎn)。子孫節(jié)點(diǎn)使用 .descendants 屬性。子節(jié)點(diǎn)可以直接獲取標(biāo)簽的直接子節(jié)點(diǎn)(沒(méi)有間接子節(jié)點(diǎn),因?yàn)槟蔷褪亲訉O節(jié)點(diǎn)了),子孫節(jié)點(diǎn)則可以獲取所有子孫節(jié)點(diǎn),看一下下面的例子:

for child in head_tag.descendants:

print(child)

>>> <title>The Dormouse's story</title>

>>> The Dormouse's stor

我們知道title是head的子節(jié)點(diǎn),而title中的字符串又是title的子節(jié)點(diǎn),所以title和title所包含的字符串都是head的子孫節(jié)點(diǎn),因此都會(huì)被查找出來(lái)。.descendants 的用法和.children 是一樣的,會(huì)返回一個(gè)生成器,所以需要先轉(zhuǎn)化為list再進(jìn)行遍歷。

父節(jié)點(diǎn)

對(duì)于父節(jié)點(diǎn),我們可以使用 .parents 得到父標(biāo)簽。

title_tag = soup.title

title_tag

>>> <title>The Dormouse's story</title>

title_tag.parents

>>> <head><title>The Dormouse's story</title></head>

title_tag.parents.name

>>> head

如果要獲得全部父節(jié)點(diǎn)則可以使用 .parents ,就能得到所有父節(jié)點(diǎn)。

link = soup.a

for parent in link.parents:

if parent is None:

print(parent)

else:

print(parent.name)

>>>

p body html [document] None

我們可以看到a節(jié)點(diǎn)的所有父標(biāo)簽都被遍歷了,包括BeautifulSoup對(duì)象本身的[document]。

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

兄弟節(jié)點(diǎn)使用 .next_sibling 和 .previous_sibling 來(lái)進(jìn)行獲取,其中next_sibling 是用來(lái)獲取下一個(gè)兄弟節(jié)點(diǎn),而previous_sibling 是獲取前一個(gè)兄弟節(jié)點(diǎn)。

a_tag = soup.find("a", id="link1")

a_tag.next_sibling

>>> ,

a_tag.previous_element

>>>

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

同樣,你可以可以通過(guò) .next_siblings.previous.siblings獲取所有前后兄弟節(jié)點(diǎn),返回結(jié)果也是一個(gè)生成器。

說(shuō)完了節(jié)點(diǎn)的獲取,接下來(lái)說(shuō)一下如何提取已經(jīng)獲取的節(jié)點(diǎn)的內(nèi)容呢?

節(jié)點(diǎn)內(nèi)容

前面說(shuō)過(guò)對(duì)于NavigableString對(duì)象,我們可以采用 .string 來(lái)獲取文本信息。如果tag只有一個(gè)NavigableString 類型的子節(jié)點(diǎn),那么這個(gè)tag可以使用 .string 得到文本信息,就像之前提到的一樣??聪旅娴膖itle和head標(biāo)簽:

title_tag.string

>>> 'The Dormouse's story'

head_tag.contents

>>> [<title>The Dormouse's story</title>]

head_tag.string

>>> 'The Dormouse's story'

上面那種方法只適用于tag只有一個(gè)NavigableString 類型的子節(jié)點(diǎn)情況,如果這個(gè)tag里面有多個(gè)節(jié)點(diǎn),那就不行了,因?yàn)閠ag無(wú)法確定該調(diào)用哪個(gè)節(jié)點(diǎn),就會(huì)出現(xiàn)下面這種輸出None的情況:

print(soup.html.string)

>>> None

需要說(shuō)明的是,如果tag中包含多個(gè)字符串,我們可以使用 .strings 來(lái)循環(huán)獲取。如果輸出的字符串中包含了很多空格或空行,則可以使用 .stripped_strings 來(lái)去除多余的空白內(nèi)容(包括空格和空行)。

現(xiàn)在有一個(gè)問(wèn)題了,你上面介紹的都是如何遍歷各個(gè)節(jié)點(diǎn),可是有時(shí)候我不需要你進(jìn)行遍歷全部,那樣會(huì)增加運(yùn)行時(shí)間,我只需要提取我需要的那部分即可,所以我們就可以搜索文檔,直接輸出滿意的結(jié)果就行。

BeautifulSoup搜索文檔樹

搜索文檔樹有很多方法,match,find,find_all...,這里介紹比較常用的fnd_all()。fnd_all()它可以設(shè)置過(guò)濾條件,直接返回滿足條件的值。

find_all()語(yǔ)法格式:

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

通過(guò)一個(gè)簡(jiǎn)單的例子,來(lái)感受一下它的魅力:

soup.find_all("a")

>>>

[<a class="sister" id="link1">Elsie</a>,

<a class="sister" id="link2">Lacie</a>,

<a class="sister" id="link3">Tillie</a>]

soup.find_all(id="link3")

>>>

<a class="sister" id="link3">Tillie</a>]

下面簡(jiǎn)單介紹一下它的幾個(gè)重要的參數(shù):name,keywords。

Name參數(shù)

name就是標(biāo)簽的名字,如在上面的例子中尋找所有的a標(biāo)簽,name參數(shù)可以是字符串、True、正則表達(dá)式、列表、甚至是具體的方法。

Keyword參數(shù)

這種形式非常類似于我們Python中對(duì)字典的操作,通過(guò)設(shè)置key這個(gè)過(guò)濾條件來(lái)獲取指定信息:

soup.find_all(id="link3")

>>>

<a class="sister" id="link3">Tillie</a>]

這里找到了id為link3的a標(biāo)簽信息。當(dāng)然也是可以采用關(guān)鍵字的方式:

soup.find_all(href=re.compile("lacie"))

>>>

[<a class="sister" id="link2">Lacie</a>]

這里找到了href屬性里含有“lacie”字樣的a標(biāo)簽的信息,我們也可以同時(shí)定義多個(gè)關(guān)鍵字來(lái)進(jìn)行更嚴(yán)格的過(guò)濾:

soup.find_all(href=re.compile("lacie"), id='link2')

>>>

[<a class="sister" id="link2">Lacie</a>]

簡(jiǎn)單再說(shuō)一下match和search的用法:你只要記住match 方法用于查找字符串的頭部(也可以指定起始位置),它是一次匹配,只要找到了一個(gè)匹配的結(jié)果就返回,而不是查找所有匹配的結(jié)果。search則是全局搜索,用于查找字符串的任何位置,它也是一次匹配,只要找到了一個(gè)匹配的結(jié)果就返回,而不是查找所有匹配的結(jié)果。關(guān)于其他方法的介紹請(qǐng)點(diǎn)擊閱讀原文進(jìn)行查看吧。

好了本篇關(guān)于用BeautifulSoup來(lái)煲美味的湯的介紹就到此為止了,感謝你的賞閱!

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
BeautifulSoup庫(kù)詳解(個(gè)人整理)
BeautifulSoup的使用
實(shí)現(xiàn)關(guān)鍵詞高亮:在HTML字符串中匹配“跨標(biāo)簽關(guān)鍵詞”
bs4介紹
bs4網(wǎng)頁(yè)解析庫(kù)安裝
Beautiful Soup模塊詳解
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服