您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“python beautifulsoup4模塊怎么用”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“python beautifulsoup4模塊怎么用”吧!
BeautifulSoup4
是一款 python 解析庫,主要用于解析 HTML 和 XML,在爬蟲知識體系中解析 HTML 會比較多一些,
該庫安裝命令如下:
pip install beautifulsoup4
BeautifulSoup
在解析數(shù)據(jù)時,需依賴第三方解析器,常用解析器與優(yōu)勢如下所示:
python 標(biāo)準(zhǔn)庫 html.parser
:python 內(nèi)置標(biāo)準(zhǔn)庫,容錯能力強;
lxml 解析器
:速度快,容錯能力強;
html5lib
:容錯性最強,解析方式與瀏覽器一致。
接下來用一段自定義的 HTML 代碼來演示 beautifulsoup4
庫的基本使用,測試代碼如下:
<html> <head> <title>測試bs4模塊腳本</title> </head> <body> <h2>橡皮擦的爬蟲課</h2> <p>用一段自定義的 HTML 代碼來演示</p> </body> </html>
使用 BeautifulSoup
對其進(jìn)行簡單的操作,包含實例化 BS 對象,輸出頁面標(biāo)簽等內(nèi)容。
from bs4 import BeautifulSoup text_str = """<html> <head> <title>測試bs4模塊腳本</title> </head> <body> <h2>橡皮擦的爬蟲課</h2> <p>用1段自定義的 HTML 代碼來演示</p> <p>用2段自定義的 HTML 代碼來演示</p> </body> </html> """ # 實例化 Beautiful Soup 對象 soup = BeautifulSoup(text_str, "html.parser") # 上述是將字符串格式化為 Beautiful Soup 對象,你可以從一個文件進(jìn)行格式化 # soup = BeautifulSoup(open('test.html')) print(soup) # 輸入網(wǎng)頁標(biāo)題 title 標(biāo)簽 print(soup.title) # 輸入網(wǎng)頁 head 標(biāo)簽 print(soup.head) # 測試輸入段落標(biāo)簽 p print(soup.p) # 默認(rèn)獲取第一個
我們可以通過 BeautifulSoup 對象,直接調(diào)用網(wǎng)頁標(biāo)簽,這里存在一個問題,通過 BS 對象調(diào)用標(biāo)簽只能獲取排在第一位置上的標(biāo)簽,如上述代碼中,只獲取到了一個 p
標(biāo)簽,如果想要獲取更多內(nèi)容,請繼續(xù)閱讀。
學(xué)習(xí)到這里,我們需要了解 BeautifulSoup 中的 4 個內(nèi)置對象:
BeautifulSoup
:基本對象,整個 HTML 對象,一般當(dāng)做 Tag 對象看即可;
Tag
:標(biāo)簽對象,標(biāo)簽就是網(wǎng)頁中的各個節(jié)點,例如 title,head,p;
NavigableString
:標(biāo)簽內(nèi)部字符串;
Comment
:注釋對象,爬蟲里面使用場景不多。
下述代碼為你演示這幾種對象出現(xiàn)的場景,注意代碼中的相關(guān)注釋:
from bs4 import BeautifulSoup text_str = """<html> <head> <title>測試bs4模塊腳本</title> </head> <body> <h2>橡皮擦的爬蟲課</h2> <p>用1段自定義的 HTML 代碼來演示</p> <p>用2段自定義的 HTML 代碼來演示</p> </body> </html> """ # 實例化 Beautiful Soup 對象 soup = BeautifulSoup(text_str, "html.parser") # 上述是將字符串格式化為 Beautiful Soup 對象,你可以從一個文件進(jìn)行格式化 # soup = BeautifulSoup(open('test.html')) print(soup) print(type(soup)) # <class 'bs4.BeautifulSoup'> # 輸入網(wǎng)頁標(biāo)題 title 標(biāo)簽 print(soup.title) print(type(soup.title)) # <class 'bs4.element.Tag'> print(type(soup.title.string)) # <class 'bs4.element.NavigableString'> # 輸入網(wǎng)頁 head 標(biāo)簽 print(soup.head)
對于 Tag 對象,有兩個重要的屬性,是 name
和 attrs
from bs4 import BeautifulSoup text_str = """<html> <head> <title>測試bs4模塊腳本</title> </head> <body> <h2>橡皮擦的爬蟲課</h2> <p>用1段自定義的 HTML 代碼來演示</p> <p>用2段自定義的 HTML 代碼來演示</p> <a href="http://www.csdn.net" rel="external nofollow" rel="external nofollow" >CSDN 網(wǎng)站</a> </body> </html> """ # 實例化 Beautiful Soup 對象 soup = BeautifulSoup(text_str, "html.parser") print(soup.name) # [document] print(soup.title.name) # 獲取標(biāo)簽名 title print(soup.html.body.a) # 可以通過標(biāo)簽層級獲取下層標(biāo)簽 print(soup.body.a) # html 作為一個特殊的根標(biāo)簽,可以省略 print(soup.p.a) # 無法獲取到 a 標(biāo)簽 print(soup.a.attrs) # 獲取屬性
上述代碼演示了獲取 name
屬性和 attrs
屬性的用法,其中 attrs
屬性得到的是一個字典,可以通過鍵獲取對應(yīng)的值。
獲取標(biāo)簽的屬性值,在 BeautifulSoup 中,還可以使用如下方法:
print(soup.a["href"]) print(soup.a.get("href"))
獲取 NavigableString
對象 獲取了網(wǎng)頁標(biāo)簽之后,就要獲取標(biāo)簽內(nèi)文本了,通過下述代碼進(jìn)行。
print(soup.a.string)
除此之外,你還可以使用 text
屬性和 get_text()
方法獲取標(biāo)簽內(nèi)容。
print(soup.a.string) print(soup.a.text) print(soup.a.get_text())
還可以獲取標(biāo)簽內(nèi)所有文本,使用 strings
和 stripped_strings
即可。
print(list(soup.body.strings)) # 獲取到空格或者換行 print(list(soup.body.stripped_strings)) # 去除空格或者換行
擴(kuò)展標(biāo)簽/節(jié)點選擇器之遍歷文檔樹
直接子節(jié)點
標(biāo)簽(Tag)對象的直接子元素,可以使用 contents
和 children
屬性獲取。
from bs4 import BeautifulSoup text_str = """<html> <head> <title>測試bs4模塊腳本</title> </head> <body> <div id="content"> <h2>橡皮擦的爬蟲課<span>最棒</span></h2> <p>用1段自定義的 HTML 代碼來演示</p> <p>用2段自定義的 HTML 代碼來演示</p> <a href="http://www.csdn.net" rel="external nofollow" rel="external nofollow" >CSDN 網(wǎng)站</a> </div> <ul class="nav"> <li>首頁</li> <li>博客</li> <li>專欄課程</li> </ul> </body> </html> """ # 實例化 Beautiful Soup 對象 soup = BeautifulSoup(text_str, "html.parser") # contents 屬性獲取節(jié)點的直接子節(jié)點,以列表的形式返回內(nèi)容 print(soup.div.contents) # 返回列表 # children 屬性獲取的也是節(jié)點的直接子節(jié)點,以生成器的類型返回 print(soup.div.children) # 返回 <list_iterator object at 0x00000111EE9B6340>
請注意以上兩個屬性獲取的都是直接子節(jié)點,例如 h2
標(biāo)簽內(nèi)的后代標(biāo)簽 span
,不會單獨獲取到。
如果希望將所有的標(biāo)簽都獲取到,使用 descendants
屬性,它返回的是一個生成器,所有標(biāo)簽包括標(biāo)簽內(nèi)的文本都會單獨獲取。
print(list(soup.div.descendants))
其它節(jié)點的獲?。私饧纯桑床榧从茫?/p>
parent
和 parents
:直接父節(jié)點和所有父節(jié)點;
next_sibling
,next_siblings
,previous_sibling
,previous_siblings
:分別表示下一個兄弟節(jié)點、下面所有兄弟節(jié)點、上一個兄弟節(jié)點、上面所有兄弟節(jié)點,由于換行符也是一個節(jié)點,所有在使用這幾個屬性時,要注意一下?lián)Q行符;
next_element
,next_elements
,previous_element
,previous_elements
:這幾個屬性分別表示上一個節(jié)點或者下一個節(jié)點,注意它們不分層次,而是針對所有節(jié)點,例如上述代碼中 div
節(jié)點的下一個節(jié)點是 h2
,而 div
節(jié)點的兄弟節(jié)點是 ul
。
文檔樹搜索相關(guān)函數(shù)
第一個要學(xué)習(xí)的函數(shù)就是 find_all()
函數(shù),原型如下所示:
find_all(name,attrs,recursive,text,limit=None,**kwargs)
name
:該參數(shù)為 tag 標(biāo)簽的名字,例如 find_all('p')
是查找所有的 p
標(biāo)簽,可接受標(biāo)簽名字符串、正則表達(dá)式與列表;
attrs
:傳入的屬性,該參數(shù)可以字典的形式傳入,例如 attrs={'class': 'nav'}
,返回的結(jié)果是 tag 類型的列表;
上述兩個參數(shù)的用法示例如下:
print(soup.find_all('li')) # 獲取所有的 li print(soup.find_all(attrs={'class': 'nav'})) # 傳入 attrs 屬性 print(soup.find_all(re.compile("p"))) # 傳遞正則,實測效果不理想 print(soup.find_all(['a','p'])) # 傳遞列表
recursive
:調(diào)用 find_all ()
方法時,BeautifulSoup 會檢索當(dāng)前 tag 的所有子孫節(jié)點,如果只想搜索 tag 的直接子節(jié)點,可以使用參數(shù) recursive=False
,測試代碼如下:
print(soup.body.div.find_all(['a','p'],recursive=False)) # 傳遞列表
text
:可以檢索文檔中的文本字符串內(nèi)容,與 name
參數(shù)的可選值一樣,text
參數(shù)接受標(biāo)簽名字符串、正則表達(dá)式、 列表;
print(soup.find_all(text='首頁')) # ['首頁'] print(soup.find_all(text=re.compile("^首"))) # ['首頁'] print(soup.find_all(text=["首頁",re.compile('課')])) # ['橡皮擦的爬蟲課', '首頁', '專欄課程']
limit
:可以用來限制返回結(jié)果的數(shù)量;
kwargs
:如果一個指定名字的參數(shù)不是搜索內(nèi)置的參數(shù)名,搜索時會把該參數(shù)當(dāng)作 tag 的屬性來搜索。這里要按 class
屬性搜索,因為 class
是 python 的保留字,需要寫作 class_
,按 class_
查找時,只要一個 CSS 類名滿足即可,如需多個 CSS 名稱,填寫順序需要與標(biāo)簽一致。
print(soup.find_all(class_ = 'nav')) print(soup.find_all(class_ = 'nav li'))
還需要注意網(wǎng)頁節(jié)點中,有些屬性在搜索中不能作為kwargs
參數(shù)使用,比如html5
中的 data-*
屬性,需要通過attrs
參數(shù)進(jìn)行匹配。
與
find_all()
方法用戶基本一致的其它方法清單如下:
find()
:函數(shù)原型find( name , attrs , recursive , text , **kwargs )
,返回一個匹配元素;
find_parents(),find_parent()
:函數(shù)原型 find_parent(self, name=None, attrs={}, **kwargs)
,返回當(dāng)前節(jié)點的父級節(jié)點;
find_next_siblings(),find_next_sibling()
:函數(shù)原型 find_next_sibling(self, name=None, attrs={}, text=None, **kwargs)
,返回當(dāng)前節(jié)點的下一兄弟節(jié)點;
find_previous_siblings(),find_previous_sibling()
:同上,返回當(dāng)前的節(jié)點的上一兄弟節(jié)點;
find_all_next(),find_next(),find_all_previous () ,find_previous ()
:函數(shù)原型 find_all_next(self, name=None, attrs={}, text=None, limit=None, **kwargs)
,檢索當(dāng)前節(jié)點的后代節(jié)點。
CSS 選擇器 該小節(jié)的知識點與pyquery
有點撞車,核心使用select()
方法即可實現(xiàn),返回數(shù)據(jù)是列表元組。
通過標(biāo)簽名查找,soup.select("title")
;
通過類名查找,soup.select(".nav")
;
通過 id 名查找,soup.select("#content")
;
通過組合查找,soup.select("div#content")
;
通過屬性查找,soup.select("div[id='content'")
,soup.select("a[href]")
;
在通過屬性查找時,還有一些技巧可以使用,例如:
^=
:可以獲取以 XX 開頭的節(jié)點:
print(soup.select('ul[class^="na"]'))
*=
:獲取屬性包含指定字符的節(jié)點:
print(soup.select('ul[class*="li"]'))
BeautifulSoup 的基礎(chǔ)知識掌握之后,在進(jìn)行爬蟲案例的編寫,就非常簡單了,本次要采集的目標(biāo)網(wǎng)站 ,該目標(biāo)網(wǎng)站有大量的藝術(shù)二維碼,可以供設(shè)計大哥做參考。
下述應(yīng)用到了 BeautifulSoup 模塊的標(biāo)簽檢索與屬性檢索,完整代碼如下:
from bs4 import BeautifulSoup import requests import logging logging.basicConfig(level=logging.NOTSET) def get_html(url, headers) -> None: try: res = requests.get(url=url, headers=headers, timeout=3) except Exception as e: logging.debug("采集異常", e) if res is not None: html_str = res.text soup = BeautifulSoup(html_str, "html.parser") imgs = soup.find_all(attrs={'class': 'lazy'}) print("獲取到的數(shù)據(jù)量是", len(imgs)) datas = [] for item in imgs: name = item.get('alt') src = item["src"] logging.info(f"{name},{src}") # 獲取拼接數(shù)據(jù) datas.append((name, src)) save(datas, headers) def save(datas, headers) -> None: if datas is not None: for item in datas: try: # 抓取圖片 res = requests.get(url=item[1], headers=headers, timeout=5) except Exception as e: logging.debug(e) if res is not None: img_data = res.content with open("./imgs/{}.jpg".format(item[0]), "wb+") as f: f.write(img_data) else: return None if __name__ == '__main__': headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36" } url_format = "http://www.9thws.com/#p{}" urls = [url_format.format(i) for i in range(1, 2)] get_html(urls[0], headers)
本次代碼測試輸出采用的 logging
模塊實現(xiàn),效果如下圖所示。 測試僅采集了 1 頁數(shù)據(jù),如需擴(kuò)大采集范圍,只需要修改 main
函數(shù)內(nèi)頁碼規(guī)則即可。 ==代碼編寫過程中,發(fā)現(xiàn)數(shù)據(jù)請求是類型是 POST,數(shù)據(jù)返回格式是 JSON,所以本案例僅作為 BeautifulSoup 的上手案例吧==
到此,相信大家對“python beautifulsoup4模塊怎么用”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。