久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Python 爬蟲(三):BeautifulSoup 庫(kù)

 文炳春秋 2020-03-13

BeautifulSoup 是一個(gè)可以從 HTML 或 XML 文件中提取數(shù)據(jù)的 Python 庫(kù),,它能夠?qū)?HTML 或 XML 轉(zhuǎn)化為可定位的樹形結(jié)構(gòu),,并提供了導(dǎo)航、查找、修改功能,它會(huì)自動(dòng)將輸入文檔轉(zhuǎn)換為 Unicode 編碼,輸出文檔轉(zhuǎn)換為 UTF-8 編碼,。

BeautifulSoup 支持 Python 標(biāo)準(zhǔn)庫(kù)中的 HTML 解析器和一些第三方的解析器,默認(rèn)使用 Python 標(biāo)準(zhǔn)庫(kù)中的 HTML 解析器,,默認(rèn)解析器效率相對(duì)比較低,,如果需要解析的數(shù)據(jù)量比較大或比較頻繁,推薦使用更強(qiáng),、更快的 lxml 解析器,。

1 安裝

1)BeautifulSoup 安裝
如果使用 Debain 或 ubuntu 系統(tǒng),可以通過系統(tǒng)的軟件包管理來安裝:apt-get install Python-bs4,,如果無法使用系統(tǒng)包管理安裝,,可以使用 pip install beautifulsoup4 來安裝。

2)第三方解析器安裝
如果需要使用第三方解釋器 lxml 或 html5lib,,可是使用如下命令進(jìn)行安裝:apt-get install Python-lxml(html5lib)pip install lxml(html5lib),。

看一下主要解析器和它們的優(yōu)缺點(diǎn):

解析器 使用方法 優(yōu)勢(shì) 劣勢(shì)
Python標(biāo)準(zhǔn)庫(kù) BeautifulSoup(markup, "html.parser") Python的內(nèi)置標(biāo)準(zhǔn)庫(kù); 執(zhí)行速度適中,; 文檔容錯(cuò)能力強(qiáng),。 Python 2.7.3 or 3.2.2)前的版本中文檔容錯(cuò)能力差。
lxml HTML 解析器 BeautifulSoup(markup, "lxml") 速度快,;文檔容錯(cuò)能力強(qiáng),。 需要安裝C語(yǔ)言庫(kù),。
lxml XML 解析器

BeautifulSoup(markup, ["lxml-xml"])

BeautifulSoup(markup, "xml")

速度快,;唯一支持XML的解析器。 需要安裝C語(yǔ)言庫(kù)
html5lib BeautifulSoup(markup, "html5lib") 最好的容錯(cuò)性,; 以瀏覽器的方式解析文檔,; 生成HTML5格式的文檔。 速度慢,; 不依賴外部擴(kuò)展,。

2 快速上手

將一段文檔傳入 BeautifulSoup 的構(gòu)造方法,就能得到一個(gè)文檔的對(duì)象,,可以傳入一段字符串或一個(gè)文件句柄,,示例如下:

1)使用字符串
我們以如下一段 HTML 字符串為例:

html = '''
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>BeautifulSoup學(xué)習(xí)</title>
</head>
<body>
Hello BeautifulSoup
</body>
</html>
'''

使用示例如下:

from bs4 import BeautifulSoup
#使用默認(rèn)解析器
soup = BeautifulSoup(html,'html.parser')
#使用 lxml 解析器
soup = BeautifulSoup(html,'lxml')

2)本地文件
還以上面那段 HTML 為例,將上面 HTML 字符串放在 index.html 文件中,使用示例如下:

#使用默認(rèn)解析器
soup = BeautifulSoup(open('index.html'),'html.parser')
#使用 lxml 解析器
soup = BeautifulSoup(open('index.html'),'lxml')

2.1 對(duì)象的種類

BeautifulSoup 將 HTML 文檔轉(zhuǎn)換成一個(gè)樹形結(jié)構(gòu),,每個(gè)節(jié)點(diǎn)都是 Python 對(duì)象,,所有對(duì)象可以歸納為4種:TagNavigableString,,BeautifulSoup,,Comment

1)Tag 對(duì)象
Tag 對(duì)象與 HTML 或 XML 原生文檔中的 tag 相同,,示例如下:

soup = BeautifulSoup('<title>BeautifulSoup學(xué)習(xí)</title>','lxml')
tag = soup.title
tp =type(tag)
print(tag)
print(tp)

#輸出結(jié)果
'''
<title>BeautifulSoup學(xué)習(xí)</title>
<class 'bs4.element.Tag'>
'''

Tag 有很多方法和屬性,,這里先看一下它的的兩種常用屬性:nameattributes

我們可以通過 .name 來獲取 tag 的名字,,示例如下:

soup = BeautifulSoup('<title>BeautifulSoup學(xué)習(xí)</title>','lxml')
tag = soup.title
print(tag.name)

#輸出結(jié)果
#title

我們還可以修改 tag 的 name,,示例如下:

tag.name = 'title1'
print(tag)

#輸出結(jié)果
#<title1>BeautifulSoup學(xué)習(xí)</title1>

一個(gè) tag 可能有很多個(gè)屬性,先看一它的 class 屬性,,其屬性的操作方法與字典相同,,示例如下:

soup = BeautifulSoup('<title class="tl">BeautifulSoup學(xué)習(xí)</title>','lxml')
tag = soup.title
cls = tag['class']
print(cls)

#輸出結(jié)果
#['tl']

我們還可以使用 .attrs 來獲取,示例如下:

ats = tag.attrs
print(ats)

#輸出結(jié)果
#{'class': ['tl']}

tag 的屬性可以被添加,、修改和刪除,,示例如下:

#添加 id 屬性
tag['id'] = 1

#修改 class 屬性
tag['class'] = 'tl1'

#刪除 class 屬性
del tag['class']

2)NavigableString 對(duì)象
NavigableString 類是用來包裝 tag 中的字符串內(nèi)容的,使用 .string 來獲取字符串內(nèi)容,,示例如下:

str = tag.string

可以使用 replace_with() 方法將原有字符串內(nèi)容替換成其它內(nèi)容 ,,示例如下:

tag.string.replace_with('BeautifulSoup')

3)BeautifulSoup 對(duì)象
BeautifulSoup 對(duì)象表示的是一個(gè)文檔的全部?jī)?nèi)容,它并不是真正的 HTML 或 XML 的 tag,,因此它沒有 nameattribute 屬性,,為方便查看它的 name 屬性,BeautifulSoup 對(duì)象包含了一個(gè)值為 [document] 的特殊屬性 .name,,示例如下:

soup = BeautifulSoup('<title class="tl">BeautifulSoup學(xué)習(xí)</title>','lxml')
print(soup.name)

#輸出結(jié)果
#[document]

4)Comment 對(duì)象
Comment 對(duì)象是一個(gè)特殊類型的 NavigableString 對(duì)象,,它會(huì)使用特殊的格式輸出,看一下例子:

soup = BeautifulSoup('<title class="tl">Hello BeautifulSoup</title>','html.parser')
comment = soup.title.prettify()
print(comment)

#輸出結(jié)果
'''
<title class="tl">
 Hello BeautifulSoup
</title>
'''

我們前面看的例子中 tag 中的字符串內(nèi)容都不是注釋內(nèi)容,,現(xiàn)在將字符串內(nèi)容換成注釋內(nèi)容,,我們來看一下效果:

soup = BeautifulSoup('<title class="tl"><!--Hello BeautifulSoup--></title>','html.parser')
str = soup.title.string
print(str)

#輸出結(jié)果
#Hello BeautifulSoup

通過結(jié)果我們發(fā)現(xiàn)注釋符號(hào) <!----> 被自動(dòng)去除了,這一點(diǎn)我們要注意一下,。

2.2 搜索文檔樹

BeautifulSoup 定義了很多搜索方法,,我們來具體看一下。

1)find_all()
find_all() 方法搜索當(dāng)前 tag 的所有 tag 子節(jié)點(diǎn),,方法詳細(xì)如下:find_all(name=None, attrs={}, recursive=True, text=None,limit=None, **kwargs),,來具體看一下各個(gè)參數(shù)。

name 參數(shù)可以查找所有名字為 name 的 tag,,字符串對(duì)象會(huì)被自動(dòng)忽略掉,,示例如下:

soup = BeautifulSoup('<title class="tl">Hello BeautifulSoup</title>','html.parser')
print(soup.find_all('title'))

#輸出結(jié)果
#[<title class="tl">Hello BeautifulSoup</title>]

attrs 參數(shù)定義一個(gè)字典參數(shù)來搜索包含特殊屬性的 tag,,示例如下:

soup = BeautifulSoup('<title class="tl">Hello BeautifulSoup</title>','html.parser')
soup.find_all(attrs={"class": "tl"})

調(diào)用 find_all() 方法時(shí),默認(rèn)會(huì)檢索當(dāng)前 tag 的所有子孫節(jié)點(diǎn),,通過設(shè)置參數(shù) recursive=False,,可以只搜索 tag 的直接子節(jié)點(diǎn),示例如下:

soup = BeautifulSoup('<html><head><title>Hello BeautifulSoup</title></head></html>','html.parser')
print(soup.find_all('title',recursive=False))

#輸出結(jié)果
#[]

通過 text 參數(shù)可以搜搜文檔中的字符串內(nèi)容,,它接受字符串,、正則表達(dá)式、列表,、True,,示例如下:

from bs4 import BeautifulSoup
import re

soup = BeautifulSoup('<head>myHead</head><title>BeautifulSoup</title>','html.parser')
#字符串
soup.find_all(text='BeautifulSoup')

#正則表達(dá)式
soup.find_all(soup.find_all(text=re.compile('title')))

#列表
soup.find_all(soup.find_all(text=['head','title']))

#True
soup.find_all(text=True)

limit 參數(shù)與 SQL 中的 limit 關(guān)鍵字類似,用來限制搜索的數(shù)據(jù),,示例如下:

soup = BeautifulSoup('<a id="link1" href="http:///elsie">Elsie</a><a id="link2" href="http:///elsie">Elsie</a>','html.parser')
soup.find_all('a', limit=1)

我們經(jīng)常見到 Python 中 *arg**kwargs 這兩種可變參數(shù),,*arg 表示非鍵值對(duì)的可變數(shù)量的參數(shù),將參數(shù)打包為 tuple 傳遞給函數(shù),; **kwargs 表示關(guān)鍵字參數(shù),,參數(shù)是鍵值對(duì)形式的,將參數(shù)打包為 dict 傳遞給函數(shù),。

使用多個(gè)指定名字的參數(shù)可以同時(shí)過濾 tag 的多個(gè)屬性,,如:

soup = BeautifulSoup('<a id="link1" href="http:///elsie">Elsie</a><a id="link2" href="http:///elsie">Elsie</a>','html.parser')
soup.find_all(href=re.compile("elsie"),id='link1')

有些 tag 屬性在搜索不能使用,如 HTML5 中的 data-* 屬性,,示例如下:

soup = BeautifulSoup('<div data-foo="value">foo!</div>')
soup.find_all(data-foo='value')

首先當(dāng)我在 Pycharm 中輸入 data-foo='value' 便提示語(yǔ)法錯(cuò)誤了,,然后我不管提示直接執(zhí)行提示 SyntaxError: keyword can't be an expression 這個(gè)結(jié)果也驗(yàn)證了 data-* 屬性在搜索中不能使用。我們可以通過 find_all() 方法的 attrs 參數(shù)定義一個(gè)字典參數(shù)來搜索包含特殊屬性的 tag,,示例如下:

print(soup.find_all(attrs={'data-foo': 'value'}))

2)find()
方法詳細(xì)如下:find(name=None, attrs={}, recursive=True, text=None,**kwargs),,我們可以看出除了少了 limit 參數(shù),其它參數(shù)與方法 find_all 一樣,,不同之處在于:find_all() 方法的返回結(jié)果是一個(gè)列表,,find() 方法返回的是第一個(gè)節(jié)點(diǎn),find_all() 方法沒有找到目標(biāo)是返回空列表,,find() 方法找不到目標(biāo)時(shí),,返回 None。來看個(gè)例子:

soup = BeautifulSoup('<a id="link1" href="http:///elsie">Elsie</a><a id="link2" href="http:///elsie">Elsie</a>','html.parser')
print(soup.find_all('a', limit=1))
print(soup.find('a'))

#輸出結(jié)果
'''
[<a href="http:///elsie" id="link1">Elsie</a>]
<a href="http:///elsie" id="link1">Elsie</a>
'''

從示例中我們也可以看出,,find() 方法返回的是找到的第一個(gè)節(jié)點(diǎn),。

3)find_parents() 和 find_parent()
find_all() 和 find() 用來搜索當(dāng)前節(jié)點(diǎn)的所有子節(jié)點(diǎn),,find_parents() 和 find_parent() 則用來搜索當(dāng)前節(jié)點(diǎn)的父輩節(jié)點(diǎn),。

4)find_next_siblings() 和 find_next_sibling()
這兩個(gè)方法通過 .next_siblings 屬性對(duì)當(dāng)前 tag 所有后面解析的兄弟 tag 節(jié)點(diǎn)進(jìn)行迭代,find_next_siblings() 方法返回所有符合條件的后面的兄弟節(jié)點(diǎn),,find_next_sibling() 只返回符合條件的后面的第一個(gè)tag節(jié)點(diǎn),。

5)find_previous_siblings() 和 find_previous_sibling()
這兩個(gè)方法通過 .previous_siblings 屬性對(duì)當(dāng)前 tag 前面解析的兄弟 tag 節(jié)點(diǎn)進(jìn)行迭代,,find_previous_siblings() 方法返回所有符合條件的前面的兄弟節(jié)點(diǎn),find_previous_sibling() 方法返回第一個(gè)符合條件的前面的兄弟節(jié)點(diǎn),。

6)find_all_next() 和 find_next()
這兩個(gè)方法通過 .next_elements 屬性對(duì)當(dāng)前 tag 之后的 tag 和字符串進(jìn)行迭代,,find_all_next() 方法返回所有符合條件的節(jié)點(diǎn),find_next() 方法返回第一個(gè)符合條件的節(jié)點(diǎn),。

7)find_all_previous() 和 find_previous()
這兩個(gè)方法通過 .previous_elements 屬性對(duì)當(dāng)前節(jié)點(diǎn)前面的 tag 和字符串進(jìn)行迭代,,find_all_previous() 方法返回所有符合條件的節(jié)點(diǎn),find_previous() 方法返回第一個(gè)符合條件的節(jié)點(diǎn),。

2.3 CSS選擇器

BeautifulSoup 支持大部分的 CSS 選擇器,,在 Tag 或 BeautifulSoup 對(duì)象的 .select() 方法中傳入字符串參數(shù),即可使用 CSS 選擇器的語(yǔ)法找到 tag,,返回類型為列表,。示例如下:

soup = BeautifulSoup('<body><a id="link1" class="elsie">Elsie</a><a id="link2" class="elsie">Elsie</a></body>','html.parser')
print(soup.select('a'))

#輸出結(jié)果
#[<a clss="elsie" id="link1">Elsie</a>, <a clss="elsie" id="link2">Elsie</a>]

通過標(biāo)簽逐層查找

soup.select('body a')

找到某個(gè) tag 標(biāo)簽下的直接子標(biāo)簽

soup.select('body > a')

通過類名查找

soup.select('.elsie')
soup.select('[class~=elsie]')

通過 id 查找

soup.select('#link1')

使用多個(gè)選擇器

soup.select('#link1,#link2')

通過屬性查找

soup.select('a[class]')

通過屬性的值來查找

soup.select('a[class="elsie"]')

查找元素的第一個(gè)

soup.select_one('.elsie')

查找兄弟節(jié)點(diǎn)標(biāo)簽

#查找所有
soup.select('#link1 ~ .elsie')
#查找第一個(gè)
soup.select('#link1 + .elsie')

參考:
https://beautifulsoup./zh_CN/latest/#next-siblings-previous-siblings



    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多