BeautifulSoup庫用於從HTML或XML檔案中提取資料。它可以自動將複雜的HTML文件轉換為樹形結構,並提供簡單的方法來搜尋文件中的節點,使得我們可以輕鬆地遍歷和修改HTML文件的內容。廣泛用於Web爬蟲和資料抽取應用程式中。
讀者如果需要使用這個庫,同樣需要執行pip命令用以安裝:
- 安裝PIP包:pip install bs4 -i https://pypi.tuna.tsinghua.edu.cn/simple
21.8.1 屬性定位連結
透過HTML
屬性我們可以輕鬆的實現對特定頁面特定元素的提取,如下程式碼我們首先封裝兩個函式,其中get_page_attrs
函式用於一次性解析需求,函式search_page
則用於多次對頁面進行解析,這兩個函式如果傳入attribute
屬性則用於提取屬性內的引數,而傳入text
則用於提取屬性自身文字。
import requests
from bs4 import BeautifulSoup
header = {"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98"}
# 引數1: 解析頁面URL
# 引數2: 需要解析的頁面定位
# 引數3: 提取標籤屬性
# 引數4:設定超時時間
# 引數5:設定返回型別(attribute 返回屬性欄位,text 返回文字欄位)
def get_page_attrs(url,regx,attrs,timeout,type):
respon_page = []
try:
respon = requests.get(url=url, headers=header, timeout=timeout)
if respon.status_code == 200:
if respon != None:
soup = BeautifulSoup(respon.text, "html.parser")
ret = soup.select(regx)
for item in ret:
if type == "attribute":
respon_page.append( str(item.attrs[attrs] ))
if type == "text":
respon_page.append(str(item.get_text()))
return respon_page
else:
return None
except Exception:
return None
return None
# 對頁面多次搜尋
# 引數1: 需要解析的html文字
# 引數2: 需要解析的頁面定位
# 引數3: 提取標籤屬性
# 引數5:設定返回型別(attribute 返回屬性欄位,text 返回文字欄位)
def search_page(data,regx,attrs,type):
respon_page = []
if data != None:
soup = BeautifulSoup(data, "html.parser")
ret = soup.select(regx)
for item in ret:
if type == "attribute":
respon_page.append( str(item.attrs[attrs] ))
if type == "text":
respon_page.append(str(item.get_text()))
return respon_page
透過使用上述兩個封裝函式,讀者就可以輕鬆的實現對特定網頁頁面元素的定位,首先我們透過CSS
屬性定位一篇文章中的圖片連結,這段程式碼如下;
if __name__ == "__main__":
# 透過CSS屬性定點陣圖片
ref = get_page_attrs("https://www.cnblogs.com/LyShark/p/15914868.html",
"#cnblogs_post_body > p > img",
"src",
5,
"attribute"
)
print(ref)
當上述程式碼執行後,即可提取出特定網址連結內,屬性#cnblogs_post_body > p > img
中圖片的src
屬性,並提取出圖片屬性attribute
自身引數。
接著我們繼續使用該函式實現定位文章列表功能,文章列表的定位同理,此處第二個引數應修改為href
屬性,如下程式碼分別使用兩種方式實現對文章列表的定位功能;
if __name__ == "__main__":
# 定位文章列表,兩種方式均可
ref = get_page_attrs("https://www.cnblogs.com/lyshark",
"#mainContent > div > div > div.postTitle > a",
"href",
5,
"attribute"
)
print(ref)
ref = get_page_attrs("https://www.cnblogs.com/lyshark",
"div[class='day'] div[class='postCon'] div a",
"href",
5,
"attribute"
)
print(ref)
程式碼執行後即可輸出lyshark
網站中主頁所有的文章地址資訊,輸出如下圖所示;
當需要定位文章內容時,我們只需要將第二個屬性更改為空格,並將第四個屬性修改為text
此時則代表只提取屬性內的文字。
if __name__ == "__main__":
# 定位文章文字欄位
ref = get_page_attrs("https://www.cnblogs.com/lyshark",
"div[class='day'] div[class='postCon'] div[class='c_b_p_desc']",
"",
5,
"text"
)
for index in ref:
print(index)
執行上述程式碼片段,即可提取出主頁中所有的文字資訊,如下圖所示;
如果需要在同一個頁面中多次定位那麼就需要使用search_page
函式了,如下程式碼中我們需要在一個頁面內尋找兩個元素,此時就需要定位兩次;
if __name__ == "__main__":
respon = requests.get(url="https://yiyuan.9939.com/yyk_47122/", headers=header, timeout=5)
ref = search_page(respon.text,
"body > div.hos_top > div > div.info > div.detail.word-break > h1 > a",
"",
"text"
)
print(ref)
ref = search_page(respon.text,
"body > div.hos_top > div > div.info > div.detail.word-break > div.tel > span",
"",
"text"
)
print(ref)
程式碼執行後,即可透過依次請求,分別輸出該頁面中的兩個元素,如下圖所示;
21.8.2 查詢所有標籤
使用find_all
函式,可實現從HTML
或XML
文件中查詢所有符合指定標籤和屬性的元素,返回一個列表,該函式從用於精確過濾,可同時將該頁中符合條件的資料一次性全部篩選出來。
其基本語法為:
find_all(name=None, attrs={}, recursive=True, text=None, limit=None, **kwargs)
- name:標籤名或列表,用於查詢指定標籤名的元素,如果為 True 或 None,則查詢所有標籤元素
- attrs:字典,用於指定屬性名和屬性值,用於查詢具有指定屬性名和屬性值的元素
- recursive:布林值,表示是否遞迴查詢子標籤,預設為 True
- text:字串或正規表示式,用於匹配元素的文字內容
- limit:整數,限制返回的匹配元素的數量
- kwargs:可變引數,用於查詢指定屬性名和屬性值的元素
我們以輸出CVE
漏洞列表為例,透過使用find_all
查詢頁面中所有的a
標籤,並返回一個列表,透過對列表元素的解析,依次輸出該漏洞的序號,網址,以及所對應的編號資訊。
import re
import requests
from bs4 import BeautifulSoup
header = {"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98"}
# 查詢文中 所有a標籤 且類名是c_b_p_desc_readmore的 並提取出其href欄位
# print(bs.find_all('a',class_='c_b_p_desc_readmore')[0]['href'])
# 提取 所有a標籤 且id等於blog_nav_admin 類等於menu 並提取出其href欄位
# print(bs.find_all('a',id='blog_nav_admin',class_='menu')[0]['href'])
# print(bs.find_all('a',id='blog_nav_admin',class_='menu')[0].attrs['href'])
if __name__ == "__main__":
url = "https://cassandra.cerias.purdue.edu/CVE_changes/today.html"
new_cve = []
ret = requests.get(url=url, headers=header, timeout=5)
soup = BeautifulSoup(ret.text, 'html.parser')
for index in soup.find_all('a'):
href = index.get('href')
text = index.get_text()
cve_number = re.findall("[0-9]{1,}-.*",index.get_text())
print("序號: {:20} 地址: {} CVE-{}".format(text,href,cve_number[0]))
讀者可自行執行上述程式碼,即可匹配出當前頁面中所有的CVE
漏洞編號等,如下圖所示;
21.8.3 取字串返回列表
在BeautifulSoup4中,stripped_strings
是一個生成器物件,用於獲取HTML
標籤內所有文字內容的迭代器。它會自動去除每個文字的前後空格和換行符,只返回純文字字串。stripped_strings
可以用於處理HTML
文件中的多行文字、空格等特殊符號,也可用於將元素下面的所有字串以列表的形式返回。
import requests
from bs4 import BeautifulSoup
header = {"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98"}
if __name__ == "__main__":
ret = requests.get(url="https://www.cnblogs.com/lyshark", headers=header, timeout=3)
text = str(ret.content.decode('utf-8'))
bs = BeautifulSoup(text, "html.parser")
ret = bs.select('#mainContent > div > div > div.postTitle > a > span')
for i in ret:
# 提取出字串並以列表的形式返回
string_ = list(i.stripped_strings)
print(string_)
執行後即可獲取選中元素的字串內容,並透過list
將其轉換為列表格式,如下圖所示;
透過find_all
以及stripped_strings
屬性我們實現一個簡單的抓取天氣的程式碼,以讓讀者可以更好的理解該屬性是如何被使用的,如下程式碼所示;
from bs4 import BeautifulSoup
import requests
head = {'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
ret = requests.get(url="http://www.weather.com.cn/textFC/beijing.shtml", headers=head, timeout=3)
text = str(ret.content.decode('utf-8'))
bs = BeautifulSoup(text,"html.parser")
# 定位到第一個標籤上
bs.find_all('div',class_='conMidtab')[1]
# 在conMidtab裡面找tr標籤並從第3個標籤開始儲存
tr = bs.find_all('tr')[2:]
for i in tr:
# 迴圈找程式碼中的所有td標籤
td = i.find_all('td')
# 找所有的td標籤,並找出第一個td標籤
city_td = td[0]
# 獲取目標路徑下所有的子孫非標籤字串,自動去掉空字串
city = list(city_td.stripped_strings)[0]
# 取出度數的標籤
temp = td[-5]
temperature = list(temp.stripped_strings)[0]
print('城市:{} 溫度:{}'.format(city,temperature))
我們以提取北京天氣為案例,當執行程式碼後即可取出北京市所有地區的氣溫資料,如下圖所示;
本文作者: 王瑞
本文連結: https://www.lyshark.com/post/ac89ee84.html
版權宣告: 本部落格所有文章除特別宣告外,均採用 BY-NC-SA 許可協議。轉載請註明出處!