21.8 Python 使用BeautifulSoup庫

来源:https://www.cnblogs.com/LyShark/archive/2023/10/27/17791042.html
-Advertisement-
Play Games

BeautifulSoup庫用於從HTML或XML文件中提取數據。它可以自動將複雜的HTML文檔轉換為樹形結構,並提供簡單的方法來搜索文檔中的節點,使得我們可以輕鬆地遍歷和修改HTML文檔的內容。廣泛用於Web爬蟲和數據抽取應用程式中。 ...


BeautifulSoup庫用於從HTML或XML文件中提取數據。它可以自動將複雜的HTML文檔轉換為樹形結構,並提供簡單的方法來搜索文檔中的節點,使得我們可以輕鬆地遍歷和修改HTML文檔的內容。廣泛用於Web爬蟲和數據抽取應用程式中。

讀者如果需要使用這個庫,同樣需要執行pip命令用以安裝:

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函數,可實現從HTMLXML文檔中查找所有符合指定標簽和屬性的元素,返回一個列表,該函數從用於精確過濾,可同時將該頁中符合條件的數據一次性全部篩選出來。

其基本語法為:

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 許可協議。轉載請註明出處!

文章出處:https://www.cnblogs.com/LyShark/p/17791042.html
版權聲明:本博客所有文章除特別聲明外,均採用 BY-NC-SA 許可協議。轉載請註明出處!
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • PDF(Portable Document Format)是一種常用的文檔格式,具有跨平臺相容性、保真性、安全性和交互性等特點。我們日常生活工作中的合同、報告、論文等通常都採用PDF格式,以確保文檔在不同的操作系統(例如 Windows、Mac、Linux)和設備上被查看時都能保持外觀的一致性。 P ...
  • 本章節主要講的是如何配置熱載入,會碰到什麼問題,要怎麼處理。`wmproxy`是由`Rust`編寫,已實現`http/https`代理,`socks5`代理, 反向代理,靜態文件伺服器,內網穿透,配置熱更新等, ...
  • 字元串中的BKDRHash哈希函數 在電腦科學中,哈希函數是一種將任意長度的輸入(也稱為“消息”)通過散列演算法轉換成固定長度的輸出,該輸出就是哈希值。哈希函數的一個重要特性是,對於相同的輸入,無論何時執行哈希函數,它都應該產生相同的輸出。然而,對於不同的輸入,即使它們只有微小的差別,哈希函數也應該 ...
  • 本文分享自華為雲社區《深入理解Java中的Reader類:一步步剖析》,作者:bug菌。 前言 在Java開發過程中,我們經常需要讀取文件中的數據,而數據的讀取需要一個合適的類進行處理。Java的IO包提供了許多類用於數據的讀取和寫入,其中Reader便是其中之一。本文將對Java中的Reader進 ...
  • 這是做什麼用的 框架用途 在採集大量新聞網站時,不可避免的遇到動態載入的網站,這給配模版的人增加了很大難度。本來配靜態網站只需要兩個技能點:xpath和正則,如果是動態網站的還得抓包,遇到加密的還得js逆向。 所以就需要用瀏覽器渲染這些動態網站,來減少了配模板的工作難度和技能要求。動態載入的網站在新 ...
  • Hutool它是一個Java工具集類庫,包含了很多靜態方法的封裝:流處理、時間日期處理、正則處理、加解密處理、文件處理、集合處理等,可以說是項目中幾乎所有XxxxUtil的替代品,它可以使你更多的關註代碼邏輯,優雅的寫出高效代碼,避免“複製粘貼,改改再戰”。 ...
  • 函數 (1)函數的定義 函數使用func進行定義 函數是基本的代碼塊,用於執行一個任務 Go語言至少有一個main函數 函數聲明告訴了編譯器函數的名稱,返回類型和參數 //1.無參數無返回值函數的定義 func test1(){ fmt.Println("無參數無返回值函數的定義\n") } //2 ...
  • 作者:hinotoyk 鏈接:https://juejin.cn/post/6910215219822362632 背景:某日在公司中擼代碼的時候,在一個常用的controller中添加一個方法,測試時突然報錯說註入的service為null,搗鼓一陣發現後是方法修飾符寫成private,修改成pu ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...