最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python使用BeautifulSoup抓取和解析網(wǎng)頁數(shù)據(jù)的入門教程

 更新時(shí)間:2026年05月13日 08:49:19   作者:yuanpan  
文章介紹了Python中BeautifulSoup庫用于解析HTML和提取網(wǎng)頁數(shù)據(jù)的基本使用方法,包括安裝依賴、基礎(chǔ)用法、常用API以及實(shí)際操作示例,文中詳細(xì)解釋了BeautifulSoup與requests的關(guān)系,如何抓取和解析網(wǎng)頁數(shù)據(jù),并提供了常見錯(cuò)誤和注意事項(xiàng),需要的朋友可以參考下

很多 Python 初學(xué)者學(xué)完基礎(chǔ)語法之后,都會(huì)很自然地遇到一個(gè)問題:

我能不能把網(wǎng)頁里的內(nèi)容提取下來,變成自己能處理的數(shù)據(jù)?

比如:

  • 抓取文章標(biāo)題
  • 提取商品名稱和價(jià)格
  • 收集招聘信息
  • 批量整理博客鏈接
  • 分析網(wǎng)頁中的表格和列表

這時(shí)候,BeautifulSoup 往往就是最適合入門的工具之一。

它不像大型爬蟲框架那樣一上來就有很多工程化概念,也不像正則表達(dá)式那樣容易把人繞暈。它做的事情很純粹:

幫你解析 HTML,然后從中提取你真正需要的數(shù)據(jù)。

如果你現(xiàn)在正在學(xué)習(xí) Python,又想快速上手網(wǎng)頁數(shù)據(jù)抓取,這篇文章會(huì)非常適合你。我們會(huì)從 0 開始講清楚:

  • BeautifulSoup 到底是什么
  • 它和 requests 是什么關(guān)系
  • 如何抓取網(wǎng)頁 HTML
  • 如何用 find()find_all()、select() 提取數(shù)據(jù)
  • 如何寫出一個(gè)完整的小型抓取腳本
  • 實(shí)際使用時(shí)有哪些坑要提前避開

1. BeautifulSoup 是什么

BeautifulSoup 是一個(gè)專門用來解析 HTML / XML 文檔的 Python 庫。

你可以把它理解成一個(gè)“網(wǎng)頁內(nèi)容整理器”。

網(wǎng)頁源碼本來是一大段字符串,里面夾雜了很多標(biāo)簽,比如:

<div class="article">
  <h2>Python 入門</h2>
  <a href="/post/1" rel="external nofollow"  rel="external nofollow" >查看詳情</a>
</div>

如果你直接拿字符串去切片、用正則硬摳,代碼會(huì)非常脆弱。

而 BeautifulSoup 會(huì)先把這段 HTML 解析成一個(gè)結(jié)構(gòu)化對(duì)象,然后你就可以像查樹節(jié)點(diǎn)一樣去找:

  • 某個(gè)標(biāo)簽
  • 某個(gè) class
  • 某個(gè) id
  • 某個(gè)屬性
  • 某個(gè)標(biāo)簽里的文本

這也是它名字里 Soup 的感覺所在。原本很亂的網(wǎng)頁源碼,會(huì)被它整理成更容易“舀出來”的結(jié)構(gòu)。

2. BeautifulSoup 和 requests 是什么關(guān)系

很多新手剛接觸網(wǎng)頁抓取時(shí),最容易混淆這兩個(gè)庫。

其實(shí)職責(zé)非常清楚:

  • requests:負(fù)責(zé)向網(wǎng)站發(fā)請(qǐng)求,把網(wǎng)頁內(nèi)容下載回來
  • BeautifulSoup:負(fù)責(zé)解析網(wǎng)頁內(nèi)容,并從中提取數(shù)據(jù)

所以它們常常一起出現(xiàn):

  1. 先用 requests.get() 拿到 HTML
  2. 再用 BeautifulSoup() 把 HTML 解析成對(duì)象
  3. 最后用各種選擇器提取需要的數(shù)據(jù)

一句話記?。?/p>

requests 管“拿網(wǎng)頁”,BeautifulSoup 管“拆網(wǎng)頁”。

3. 先安裝依賴

直接安裝 BeautifulSoup:

pip install beautifulsoup4

實(shí)際抓取網(wǎng)頁時(shí),通常還會(huì)配合 requests

pip install requests beautifulsoup4

如果你后面想讓解析速度更快,也可以安裝 lxml 作為解析器:

pip install lxml

不過對(duì)初學(xué)者來說,先用 Python 自帶的 html.parser 就夠了。

4. BeautifulSoup 最基礎(chǔ)的使用方式

先不要急著抓真實(shí)網(wǎng)站,先用一段本地 HTML 練手,這樣最容易理解。

from bs4 import BeautifulSoup


html = """
<html>
  <body>
    <h1>Python 學(xué)習(xí)筆記</h1>
    <p class="desc">這是一個(gè) BeautifulSoup 示例頁面</p>
    <a href="/post/1" rel="external nofollow"  rel="external nofollow" >第一篇文章</a>
    <a href="/post/2" rel="external nofollow" >第二篇文章</a>
  </body>
</html>
"""

soup = BeautifulSoup(html, "html.parser")

print(soup.h1.get_text())
print(soup.find("p", class_="desc").get_text())

這段代碼里最關(guān)鍵的是:

soup = BeautifulSoup(html, "html.parser")

它表示把字符串形式的 HTML 交給 BeautifulSoup 解析。

后面你就可以通過 soup.h1、find()、select() 這些方式去拿數(shù)據(jù)。

5. 先掌握最常用的 4 個(gè)操作

BeautifulSoup 的 API 不算少,但對(duì)于新手來說,真正最常用的就這幾個(gè)。

5.1find():找第一個(gè)匹配標(biāo)簽

title = soup.find("h1")
print(title.get_text())

如果頁面里有多個(gè) h1,它只會(huì)返回第一個(gè)匹配項(xiàng)。

你也可以加屬性條件:

desc = soup.find("p", class_="desc")

注意這里是 class_,后面要加下劃線,因?yàn)?class 是 Python 關(guān)鍵字。

5.2find_all():找所有匹配標(biāo)簽

links = soup.find_all("a")
for link in links:
    print(link.get_text(), link.get("href"))

這個(gè)方法非常適合提取列表數(shù)據(jù),比如:

  • 所有文章鏈接
  • 所有商品卡片
  • 所有招聘項(xiàng)

5.3select():用 CSS 選擇器查找

如果你有一點(diǎn)前端基礎(chǔ),會(huì)非常喜歡這個(gè)方法。

items = soup.select("a")
desc = soup.select_one("p.desc")

常見寫法:

  • div:選所有 div
  • .card:選 class 為 card 的元素
  • #main:選 id 為 main 的元素
  • .article-list a:選某個(gè)區(qū)域下面的所有鏈接

在很多實(shí)際項(xiàng)目中,select()select_one() 會(huì)比 find() 更順手。

5.4get_text()和get()

提取文本:

text = title.get_text(strip=True)

提取屬性:

href = link.get("href")

這里要區(qū)分清楚:

  • get_text():拿標(biāo)簽里的文字
  • get("href"):拿標(biāo)簽屬性

6. 寫一個(gè)稍微像樣一點(diǎn)的解析示例

下面這段示例會(huì)更接近真實(shí)項(xiàng)目。

我已經(jīng)把完整代碼整理成單獨(dú)文件,方便你本地直接運(yùn)行:

beautifulsoup_web_scraping_demo.py

代碼如下:

from __future__ import annotations

from bs4 import BeautifulSoup
import requests


SAMPLE_HTML = """
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8" />
    <title>BeautifulSoup Demo</title>
</head>
<body>
    <div class="article-list">
        <article class="article-card" data-id="101">
            <h2 class="title"><a href="/post/101" rel="external nofollow" >Python 抓取網(wǎng)頁入門</a></h2>
            <span class="author">小明</span>
            <span class="views">1280</span>
        </article>
        <article class="article-card" data-id="102">
            <h2 class="title"><a href="/post/102" rel="external nofollow" >BeautifulSoup 選擇器快速上手</a></h2>
            <span class="author">小紅</span>
            <span class="views">980</span>
        </article>
        <article class="article-card" data-id="103">
            <h2 class="title"><a href="/post/103" rel="external nofollow" >requests 和 bs4 配合實(shí)戰(zhàn)</a></h2>
            <span class="author">小李</span>
            <span class="views">1560</span>
        </article>
    </div>
</body>
</html>
"""


def parse_local_html() -> list[dict[str, str]]:
    soup = BeautifulSoup(SAMPLE_HTML, "html.parser")
    articles: list[dict[str, str]] = []

    for card in soup.select(".article-card"):
        link = card.select_one(".title a")
        author = card.select_one(".author")
        views = card.select_one(".views")

        if link is None or author is None or views is None:
            continue

        articles.append(
            {
                "id": card.get("data-id", ""),
                "title": link.get_text(strip=True),
                "url": link.get("href", ""),
                "author": author.get_text(strip=True),
                "views": views.get_text(strip=True),
            }
        )

    return articles


def fetch_page_title(url: str) -> str:
    headers = {
        "User-Agent": (
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 (KHTML, like Gecko) "
            "Chrome/124.0 Safari/537.36"
        )
    }
    response = requests.get(url, headers=headers, timeout=10)
    response.raise_for_status()

    soup = BeautifulSoup(response.text, "html.parser")
    if soup.title and soup.title.string:
        return soup.title.string.strip()
    return "頁面沒有 title"


def main() -> None:
    print("本地 HTML 解析結(jié)果:")
    for item in parse_local_html():
        print(item)

    # 真實(shí)抓取時(shí),把這里替換成你自己的目標(biāo)網(wǎng)頁。
    # 使用前請(qǐng)先確認(rèn)目標(biāo)站點(diǎn)允許抓取,并控制請(qǐng)求頻率。
    # title = fetch_page_title("https://example.com")
    # print("頁面標(biāo)題:", title)


if __name__ == "__main__":
    main()

這個(gè)示例故意分成兩部分:

  • parse_local_html():先教你專注理解 BeautifulSoup 的解析過程
  • fetch_page_title():再告訴你如何把真實(shí)網(wǎng)頁抓下來后交給 BeautifulSoup

學(xué)習(xí)這類東西時(shí),建議你也這么練:

先會(huì)“解析”,再會(huì)“抓取”,最后再把兩者組合。

7. 真實(shí)抓取網(wǎng)頁時(shí)的標(biāo)準(zhǔn)流程

很多網(wǎng)站的抓取邏輯,本質(zhì)上都可以拆成下面這幾步:

第一步:發(fā)送請(qǐng)求

import requests

response = requests.get(url, timeout=10)
html = response.text

第二步:構(gòu)造 BeautifulSoup 對(duì)象

from bs4 import BeautifulSoup

soup = BeautifulSoup(html, "html.parser")

第三步:定位數(shù)據(jù)區(qū)域

cards = soup.select(".article-card")

第四步:從每個(gè)區(qū)域中提取字段

for card in cards:
    title = card.select_one(".title").get_text(strip=True)
    link = card.select_one("a").get("href")

第五步:整理成結(jié)構(gòu)化數(shù)據(jù)

data.append({
    "title": title,
    "url": link,
})

所以你會(huì)發(fā)現(xiàn),BeautifulSoup 真正的核心工作其實(shí)是:

先找到“每條數(shù)據(jù)的邊界”,再從每條記錄里拆字段。

這也是寫抓取腳本時(shí)最重要的思維方式。

8. 新手最常見的一個(gè)誤區(qū):一上來就抓整頁

剛開始學(xué)網(wǎng)頁抓取時(shí),很多人喜歡一上來就對(duì)整頁所有標(biāo)簽亂搜。

例如頁面里有幾十個(gè) a 標(biāo)簽,你直接:

soup.find_all("a")

當(dāng)然能找到一堆鏈接,但里面往往混著:

  • 導(dǎo)航欄鏈接
  • 廣告鏈接
  • 相關(guān)文章鏈接
  • 正文鏈接
  • 頁腳鏈接

最后數(shù)據(jù)會(huì)很亂。

更好的做法是:

  1. 先找到列表區(qū)域
  2. 再在這個(gè)區(qū)域里找標(biāo)題、鏈接、作者、時(shí)間

也就是說,盡量從:

soup.select(".article-card")

這種“按塊定位”的方式入手,而不是全頁面亂抓。

9. BeautifulSoup 常見解析器怎么選

創(chuàng)建對(duì)象時(shí)你會(huì)看到第二個(gè)參數(shù):

BeautifulSoup(html, "html.parser")

這里指定的是解析器。

常見的有三個(gè):

  • html.parser:Python 自帶,安裝最省事
  • lxml:速度通常更快,項(xiàng)目里很常用
  • html5lib:容錯(cuò)更強(qiáng),但一般更重

如果你是初學(xué)者:

  • 學(xué)習(xí)階段先用 html.parser
  • 后面項(xiàng)目里再考慮 lxml

先跑通流程,比一開始糾結(jié)性能更重要。

10. 為什么有時(shí)抓不到你在瀏覽器里看到的內(nèi)容

這是 BeautifulSoup 初學(xué)者非常容易遇到的坑。

你在瀏覽器里明明看到了內(nèi)容,但 requests.get() 拿回來的 HTML 里卻沒有。

原因通常是:

頁面的數(shù)據(jù)是通過 JavaScript 動(dòng)態(tài)加載的。

也就是說,瀏覽器打開頁面后,還會(huì)繼續(xù)執(zhí)行 JS,再向接口請(qǐng)求數(shù)據(jù),最后才把內(nèi)容渲染出來。

requests 拿到的只是最初的 HTML。

這時(shí)候 BeautifulSoup 沒問題,問題在于你抓到的輸入源就不完整。

遇到這種情況,常見思路有兩個(gè):

  • 直接分析網(wǎng)頁接口,改抓接口返回的 JSON
  • 使用 Playwright、Selenium 這類瀏覽器自動(dòng)化工具

所以要記住:

BeautifulSoup 擅長解析 HTML,但它不會(huì)替你執(zhí)行前端 JavaScript。

11. 實(shí)戰(zhàn)中必須注意的幾個(gè)問題

這部分比語法更重要。

11.1 不要把網(wǎng)頁抓取理解成“復(fù)制粘貼源碼”

真正的抓取工作,不是看到標(biāo)簽就抄代碼,而是要先觀察頁面結(jié)構(gòu):

  • 每條數(shù)據(jù)的容器是什么
  • 標(biāo)題在哪個(gè)標(biāo)簽
  • 鏈接在哪個(gè)屬性
  • 時(shí)間、作者、價(jià)格是否都在固定位置

只有先分析結(jié)構(gòu),BeautifulSoup 才會(huì)變得好用。

11.2 記得加請(qǐng)求頭

有些網(wǎng)站對(duì)默認(rèn)請(qǐng)求不友好,最簡單的處理就是帶一個(gè)常見瀏覽器的 User-Agent。

headers = {
    "User-Agent": "Mozilla/5.0 ..."
}
response = requests.get(url, headers=headers, timeout=10)

11.3 記得處理異常

不要默認(rèn)所有請(qǐng)求都會(huì)成功。

response.raise_for_status()

至少先把 HTTP 錯(cuò)誤暴露出來,否則你很可能在拿一個(gè)報(bào)錯(cuò)頁做解析。

11.4 控制抓取頻率

如果你需要抓取多頁內(nèi)容,不要用極高頻率連續(xù)請(qǐng)求。

這不僅容易失敗,也可能給目標(biāo)網(wǎng)站帶來壓力。

11.5 尊重站點(diǎn)規(guī)則和數(shù)據(jù)邊界

在使用 BeautifulSoup 抓取網(wǎng)頁數(shù)據(jù)前,應(yīng)該先確認(rèn)目標(biāo)站點(diǎn)的使用條款、robots 規(guī)則以及數(shù)據(jù)使用邊界。

技術(shù)上能抓,不代表業(yè)務(wù)上就一定適合抓。

12. BeautifulSoup 適合哪些場景

BeautifulSoup 非常適合下面這些任務(wù):

  • 網(wǎng)頁結(jié)構(gòu)比較穩(wěn)定
  • 頁面主要內(nèi)容就在 HTML 中
  • 抓取規(guī)模不算特別大
  • 想快速寫一個(gè)輕量腳本
  • 想先驗(yàn)證網(wǎng)頁數(shù)據(jù)能不能提取

比如:

  • 文章列表抓取
  • 簡單商品頁抓取
  • 博客導(dǎo)航頁整理
  • 表格數(shù)據(jù)提取
  • 頁面鏈接分析

如果你只是想先把網(wǎng)頁數(shù)據(jù)提下來,再做后續(xù)分析處理,BeautifulSoup 是一個(gè)很好的起點(diǎn)。

13. BeautifulSoup 和 Scrapy 該怎么選

這個(gè)問題很多人都會(huì)問。

可以這樣理解:

  • BeautifulSoup 更像“解析工具”
  • Scrapy 更像“完整爬蟲框架”

如果你的需求是:

  • 抓 1 個(gè)到幾十個(gè)頁面
  • 快速寫腳本驗(yàn)證
  • 重點(diǎn)在網(wǎng)頁解析本身

那么 requests + BeautifulSoup 會(huì)更輕、更直接。

如果你的需求是:

  • 大量分頁抓取
  • 自動(dòng)跟進(jìn)鏈接
  • 需要統(tǒng)一導(dǎo)出、調(diào)度、去重、重試

那通常就要考慮 Scrapy 了。

所以 BeautifulSoup 并不是“低配版 Scrapy”,而是更適合入門和輕量場景的工具。

14. 給初學(xué)者的學(xué)習(xí)建議

如果你想真正學(xué)會(huì) BeautifulSoup,不建議只看語法。

更好的學(xué)習(xí)順序是:

  1. 先用本地 HTML 字符串練 find()、find_all()select()
  2. 再學(xué) requests.get() 把網(wǎng)頁拿下來
  3. 再自己挑一個(gè)結(jié)構(gòu)簡單的頁面練手
  4. 把提取結(jié)果整理成字典或列表
  5. 最后導(dǎo)出成 JSON、CSV 或?qū)懭霐?shù)據(jù)庫

你會(huì)發(fā)現(xiàn),真正的能力不是“會(huì)幾個(gè) API”,而是:

看到一個(gè)網(wǎng)頁,能快速判斷該從哪里切入提取數(shù)據(jù)。

15. 總結(jié)

BeautifulSoup 是 Python 生態(tài)里非常經(jīng)典、也非常適合新手入門的網(wǎng)頁解析庫。

它最大的價(jià)值不是“語法多高級(jí)”,而是把網(wǎng)頁提取這件事變得直觀了很多。

記住這套組合最核心的分工:

  • requests:負(fù)責(zé)抓網(wǎng)頁
  • BeautifulSoup:負(fù)責(zé)拆網(wǎng)頁
  • 你的 Python 代碼:負(fù)責(zé)整理數(shù)據(jù)和后續(xù)處理

如果你正在學(xué)習(xí) Python,又希望盡快做出一些“能解決實(shí)際問題”的小工具,那么 BeautifulSoup 非常值得你親手寫一遍。

先從本地 HTML 開始,跑通選擇器,再去抓真實(shí)網(wǎng)頁,你的進(jìn)步會(huì)快很多。

以上就是Python使用BeautifulSoup抓取和解析網(wǎng)頁數(shù)據(jù)的入門教程的詳細(xì)內(nèi)容,更多關(guān)于Python BeautifulSoup抓取和解析網(wǎng)頁數(shù)據(jù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 微信跳一跳python輔助腳本(總結(jié))

    微信跳一跳python輔助腳本(總結(jié))

    本篇文章為大家整理了關(guān)于微信跳一跳的輔助腳本內(nèi)容,這次我們給大家整理的是關(guān)于python的腳本內(nèi)容,一起來學(xué)習(xí)下。
    2018-01-01
  • 利用Python制作PPT的完整步驟

    利用Python制作PPT的完整步驟

    這篇文章主要給大家介紹了關(guān)于如何利用Python制作PPT的相關(guān)資料,主要利用的是python-pptx庫,我們可以通過寫腳本,來定時(shí)執(zhí)行更新ppt內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • python中miniconda使用小結(jié)

    python中miniconda使用小結(jié)

    Miniconda3是一個(gè)輕量級(jí)的Anaconda發(fā)行版,它包含conda包管理器和Python解釋器,本文主要介紹了python中miniconda使用小結(jié),具有一定的
    2025-04-04
  • 如何在mac版pycharm選擇python版本

    如何在mac版pycharm選擇python版本

    這篇文章主要介紹了如何在mac版pycharm選擇python版本,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Python對(duì)兩個(gè)有序列表進(jìn)行合并和排序的例子

    Python對(duì)兩個(gè)有序列表進(jìn)行合并和排序的例子

    這篇文章主要介紹了Python對(duì)兩個(gè)有序列表進(jìn)行合并和排序的例子,最終代碼經(jīng)過不斷優(yōu)化,小編非常滿意,需要的朋友可以參考下
    2014-06-06
  • 使用Python算法實(shí)現(xiàn)從字符串中提取重復(fù)子串

    使用Python算法實(shí)現(xiàn)從字符串中提取重復(fù)子串

    在文本處理和數(shù)據(jù)分析中,經(jīng)常需要從字符串中提取重復(fù)出現(xiàn)的子串,本文將解析一個(gè)高效的Python算法,用于從給定字符串中提取長度超過3的重復(fù)子串,需要的朋友可以參考下
    2025-10-10
  • python enumrate函數(shù)的具體使用

    python enumrate函數(shù)的具體使用

    enumerate()是Python內(nèi)置函數(shù),用于在遍歷序列時(shí)同時(shí)獲取索引和值,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-08-08
  • 淺談對(duì)pytroch中torch.autograd.backward的思考

    淺談對(duì)pytroch中torch.autograd.backward的思考

    這篇文章主要介紹了對(duì)pytroch中torch.autograd.backward的思考,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • 解決Python獲取字典dict中不存在的值時(shí)出錯(cuò)問題

    解決Python獲取字典dict中不存在的值時(shí)出錯(cuò)問題

    今天小編就為大家分享一篇解決Python獲取字典dict中不存在的值時(shí)出錯(cuò)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-10-10
  • python實(shí)現(xiàn)大文本文件分割成多個(gè)小文件

    python實(shí)現(xiàn)大文本文件分割成多個(gè)小文件

    這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)大文本文件分割成多個(gè)小文件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-04-04

最新評(píng)論

信宜市| 通城县| 新丰县| 侯马市| 长垣县| 册亨县| 曲周县| 新巴尔虎右旗| 岑巩县| 庆安县| 鸡西市| 敦化市| 榆树市| 清水河县| 木兰县| 莎车县| 新竹市| 宁明县| 资源县| 即墨市| 寿光市| 丰镇市| 永靖县| 桂东县| 瓦房店市| 宕昌县| 厦门市| 尉犁县| 河南省| 灯塔市| 安顺市| 工布江达县| 利川市| 长阳| 绥阳县| 古田县| 盐亭县| 鄂托克旗| 泾川县| 高青县| 黔西县|