【實作】Python 爬蟲:BeautifulSoup 抓網頁資料

Python 爬蟲(Python Web Scraping)

這篇 Python 爬蟲實作教學把前面學的串成完整流程:requests 下載網頁 → BeautifulSoup 解析 HTML → 取出資料 → 存成 CSV。示範對象就用本站——抓出部落格首頁的文章標題與連結。安裝:uv add requests beautifulsoup4

先講爬蟲禮儀(很重要):

原則做法
尊重 robots.txt爬之前看 網站/robots.txt 允許範圍
控制頻率連續請求之間 time.sleep(),不要打爆人家伺服器
表明身分設定合理的 User-Agent
能用 API 就用 API上一篇的 WordPress REST API 就比爬 HTML 穩定

BeautifulSoup 基礎:先用小例子看懂

from bs4 import BeautifulSoup

html = """
<div class="post">
  <h2><a href="/python-tutorial/">Python 教學</a></h2>
  <p class="date">2026-06-08</p>
</div>
<div class="post">
  <h2><a href="/sql-tutorial/">SQL 教學</a></h2>
  <p class="date">2026-06-10</p>
</div>
"""

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

for post in soup.select("div.post"):          # CSS 選擇器
    link = post.select_one("h2 a")
    date = post.select_one("p.date")
    print(link.text, link["href"], date.text)

執行輸出:

Python 教學 /python-tutorial/ 2026-06-08
SQL 教學 /sql-tutorial/ 2026-06-10

核心就三招:select() 用 CSS 選擇器抓一批、select_one() 抓一個、.text 取文字/["href"] 取屬性。

選擇器意義
div.postclass 為 post 的 div
#mainid 為 main 的元素
h2 ah2 底下的 a(後代)
a[href]有 href 屬性的 a

實戰:抓部落格文章清單存成 CSV

完整程式 scraper.py

import csv
import requests
from bs4 import BeautifulSoup

URL = "https://blog.che-ya.com/"
HEADERS = {"User-Agent": "Mozilla/5.0 (learning-scraper)"}

# 1. 下載網頁
r = requests.get(URL, headers=HEADERS, timeout=10)
r.raise_for_status()

# 2. 解析 HTML
soup = BeautifulSoup(r.text, "html.parser")

# 3. 取出每篇文章的標題與連結(GeneratePress 佈景的結構)
articles = []
for h2 in soup.select("h2.entry-title a"):
    articles.append({"title": h2.text.strip(), "url": h2["href"]})

# 4. 存成 CSV
with open("articles.csv", "w", encoding="utf-8-sig", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=["title", "url"])
    writer.writeheader()
    writer.writerows(articles)

print(f"共抓到 {len(articles)} 篇,已存入 articles.csv")
for a in articles[:3]:
    print(a["title"])

執行輸出(依當下文章而異):

共抓到 10 篇,已存入 articles.csv
SQL Stored Procedure
企業部署與團隊管理
排程任務與自動化工作流

怎麼知道選擇器要寫 h2.entry-title a?在瀏覽器對文章標題按右鍵 →「檢查」,看它的 HTML 結構——這是寫爬蟲最重要的偵察步驟。

多頁爬取:加上 sleep

import time

for page in range(1, 4):                     # 第 1~3 頁
    url = f"https://blog.che-ya.com/page/{page}/"
    r = requests.get(url, headers=HEADERS, timeout=10)
    soup = BeautifulSoup(r.text, "html.parser")
    titles = [a.text.strip() for a in soup.select("h2.entry-title a")]
    print(f"第 {page} 頁:{len(titles)} 篇")
    time.sleep(1)                            # 禮貌間隔

執行輸出:

第 1 頁:10 篇
第 2 頁:10 篇
第 3 頁:10 篇

常見錯誤

1. 選擇器抓到空 List

網站改版、class 名稱打錯,或內容是 JavaScript 動態載入(requests 拿到的 HTML 裡根本沒有資料)。前兩者重新檢查元素;動態網頁要改用 Playwright/Selenium 這類瀏覽器自動化工具。

2. 403 Forbidden

網站擋掉了預設的 python-requests User-Agent。設定 headers 模擬一般瀏覽器;若網站明確禁止爬取,請尊重。

3. AttributeError: ‘NoneType’ object has no attribute ‘text’

select_one() 沒找到回傳 None。跟 regex 的 match 一樣,先 if x: 再取值。

總結

爬蟲四步:requests 下載 → BeautifulSoup 解析 → select() 取資料 → 存檔;選擇器靠瀏覽器「檢查」功能偵察;守禮儀(robots.txt、sleep、User-Agent)。下一篇開始串接 AI——用 Python 呼叫 OpenAI API。

延伸閱讀