bs4,全稱BeautifulSoup 4
, 它是Python獨有的一種解析方式。也就是說只有Python語言才能夠經過這種方式去解析數據。css
BeautifulSoup 3 只支持Python2,因此已經被淘汰了。
官網的介紹是這樣的html
Beautiful Soup 提供一些簡單的、python 式的函數用來處理導航、搜索、修改分析樹等功能。它是一個工具箱,經過解析文檔爲用戶提供須要抓取的數據,由於簡單,因此不須要多少代碼就能夠寫出一個完整的應用程序。 Beautiful Soup 自動將輸入文檔轉換爲 Unicode 編碼,輸出文檔轉換爲 utf-8 編碼。你不須要考慮編碼方式,除非文檔沒有指定一個編碼方式,這時,Beautiful Soup 就不能自動識別編碼方式了。而後,你僅僅須要說明一下原始編碼方式就能夠了。 Beautiful Soup 已成爲和 lxml、html6lib 同樣出色的 python 解釋器,爲用戶靈活地提供不一樣的解析策略或強勁的速度。
看起來很複雜,我用本身的理解,通俗的解釋一下python
咱們知道一個網頁的源代碼,是由多個標籤組成,好比<html>、<div>、<td>、<span>等等組成的,而bs4就是用來幫咱們精肯定位標籤位置,從而獲取標籤或者標籤屬性中內容的工具。bs4默認自帶的解析器,可是官方推薦的是更強大 速度更快的 lxml解析器網絡
其餘解析器的優缺點
pip install bs4 pip install lxml
使用bs4解析時,推薦使用lxml解析器。這個在用xpath解析的時候也會用到函數
from bs4 import BeautifulSoup
網頁源代碼,又分爲本地已經持久化的HTML文件和網絡上直接獲取的源代碼。工具
若是是本地已經持久化的文件,能夠經過下面的方式將源代碼加載到bs4對象中測試
fp = open('xxx.html', 'r', encoding='utf-8') # lxml:解析器 soup = BeautifulSoup(fp, 'lxml')
若是是經過requests庫獲取的網頁源代碼,經過下面的方式進行加載網站
response = requests.get(url) html = response.text soup = BeautifulSoup(html, 'lxml')
c.數據解析的方法和屬性this
bs4可以將複雜的HTML轉換成一個樹形結構,每一個節點都是Python對象。編碼
soup.tagName(標籤名): 返回的是文檔中第一次出現tagName對應的標籤及其相應內容
soup.tageName1.tageName2:返回tag1中tage2的標籤及其內容
soup.find:等同於soup.tagName,返回第一個匹配到的對象
soup.find_all:返回全部的匹配到的對象。
經過查看源碼會發現,find的本質其實就是調用了find_all, 而後返回第一個元素
參數解釋:
def find(self, name=None, attrs={}, recursive=True, text=None, **kwargs): """Return only the first child of this Tag matching the given criteria.""" r = None l = self.find_all(name, attrs, recursive, text, 1, **kwargs) if l: r = l[0] return r
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-iXUox6yw-1611066850753)(C:UsersAdministratorAppDataRoamingTyporatypora-user-imagesimage-20210103164834540.png)]
上圖是我從某網站截取的部分畫面,翻譯成HTML以下(只保留了對本次分析有用的部分,爲了方便閱讀刪除了地址的域名信息)
<html> <head><titel>測試Title</titel></head> <body> <div class="test"> <ul> <li> <a href="zhaosi.html">![](123456789.jpg)<p>尼古拉斯趙四</p></a> </li> </ul> </div> <div class="nr_zt w1180"> <ul> <li> <a id="star" href="zhengshuang.html">![](5940f2cd6b759.jpg)<p>鄭爽</p></a> </li> <li> <a id="star" href="zhuyilong.html">![](5b56e0fabf5bf.jpg)<p>朱一龍</p></a> </li> <li> <a id="star" href="zhoudongyu.html">![](5a28b93be8155.jpg)<p>周冬雨</p></a> </li> <li> <a id="star" href="huyitian_1.html">![](5aa36dfbe5f61.jpg)<p>胡一天</p></a> </li> <li> <a id="star" href="yiyangqianxi.html">![](5a28d243b0382.jpg)<p>易烊千璽</p></a> </li> <li> <a id="star" href="dilireba.html">![](5a28b69334087.jpg)<p>迪麗熱巴</p></a> </li> </ul> </div> </body> </html>
看下面幾個例子
# 獲取第一個li標籤 # <li> <a href="http://www.win4000.com/mt/zhengshuang.html">![](http://pic1.win4000.com/tj/2017-06-14/5940f2cd6b759.jpg)<p>鄭爽</p></a> </li> print(soup.li) # # 獲取第一個li標籤中a標籤 # <a href="http://www.win4000.com/mt/zhengshuang.html">![](http://pic1.win4000.com/tj/2017-06-14/5940f2cd6b759.jpg)<p>鄭爽</p></a> print(soup.li.a) #獲取第一個li標籤中a標籤 print(soup.find('li').a) # 獲取全部li標籤 print(soup.find_all('li')) # 獲取title標籤 print(soup.title) # 獲取a標籤的父級標籤 print(soup.a.parent) # 獲取a標籤的父級標籤的名字 print(soup.a.parent.name)
如何獲取HTML中的href?
分析:href是a標籤中的一個屬性,而a標籤又在li標籤中
在bs4中提取標籤中的屬性能夠經過attrs來獲取
from bs4 import BeautifulSoup fp = open('baidu.html', 'r', encoding='utf-8') soup = BeautifulSoup(fp, 'lxml') # 若是獲取一個能夠這樣寫 result = soup.a.attrs['href'] # zhaosi.html print(result) # 獲取所有,可經過先獲取a標籤 而後遍歷獲取 all_result = soup.find_all('a') for i in all_result: print(i.attrs['href']) print("* " * 40) # 若是我只想獲取id = star的href,須要先對id進行篩選 # 返回全部包含id=star的a標籤 star_result = soup.find_all('a', id='star') for i in star_result: print(i.attrs['href']) # 返回包含id的標籤(只要有id屬性,而且有值的標籤都返回) soup.find_all(id=True) # 假設尼古拉斯趙四 不是第一個a標籤中的內容.提取對應的href # 須要先定位class=‘test’對應div的位置 # 方法一: result = soup.find('div', 'test') print(result.a['href']) # 方法二(class爲python中關鍵字,所以查找html中的class屬性須要添加個下劃線 class_) result1 = soup.find('div', class_='test') print(result1.a['href']) # 方法三 result2 = soup.find('div', attrs={'class': 'test'}) # 獲取第一個a標籤中的文本內容 print(soup.a.text) a_result = soup.find_all('a') for i in a_result: # 生成的是一個迭代器 print(i.strings) print(list(i.strings)) print(i.string) print(i.text)
其餘補充
# 返回子孫節點 # children返回迭代器 result = soup.a.children for i in result: print(i) # 返回子孫節點, contents返回列表 r = soup.a.contents print(r) # 能夠經過正則對某個屬性進行匹配 # 好比返回href中以zh開頭的標籤 import re reg = re.compile('^zh') result = soup.find_all(href=reg) print(result)
bs4很是強大,還支持css選擇器。經過select來完成
<html> <head><titel>測試Title</titel></head> <body> <div class="test"> <ul> <li> <a href="zhaosi.html">![](123456789.jpg)<p>尼古拉斯趙四</p></a> </li> </ul> </div> <div class="nr_zt w1180"> <ul> <li> <a id="star" href="zhengshuang.html">![](5940f2cd6b759.jpg)<p>鄭爽</p></a> </li> <li> <a id="star" href="zhuyilong.html">![](5b56e0fabf5bf.jpg)<p>朱一龍</p></a> </li> <li> <a id="star" href="zhoudongyu.html">![](5a28b93be8155.jpg)<p>周冬雨</p></a> </li> <li> <a id="star" href="huyitian_1.html">![](5aa36dfbe5f61.jpg)<p>胡一天</p></a> </li> <li> <a id="star" href="yiyangqianxi.html">![](5a28d243b0382.jpg)<p>易烊千璽</p></a> </li> <li> <a id="star" href="dilireba.html">![](5a28b69334087.jpg)<p>迪麗熱巴</p></a> </li> </ul> </div> </body> </html>
from bs4 import BeautifulSoup fp = open('baidu.html', 'r', encoding='utf-8') soup = BeautifulSoup(fp, 'lxml') # 返回一個全部a標籤的列表 result = soup.select('a') # 返回第一個 result1 = soup.select('a')[0] """ class選擇器 : .className """ # 一層一層的進行選擇,用 > 鏈接 即 > : 表示一個層級 # 輸出 class = nr_zt 下ul下的li下的a標籤集合 a = soup.select('.nr_zt > ul > li > a') # 多個層級關聯,使用 空格。 # 輸出 class= 'nr_zt' 下的a標籤集合 b = soup.select('.nr_zt a') """ id選擇器: # idName """ result = soup.select('#star') # 經過href屬性查找,返回列表 soup.select('a[href="zhengshuang.html"]') # 獲取對應標籤中img標籤的src值 a = soup.select('a[href="zhengshuang.html"]')[0] print(a.img['src']) # 5940f2cd6b759.jpg
以上就是bs4的經常使用操做代碼,實際上在具體的爬蟲過程當中,匹配的方式比較靈活,因此你們也不用能夠的去背,只須要記住其原理便可。