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.post | class 為 post 的 div |
#main | id 為 main 的元素 |
h2 a | h2 底下的 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。
延伸閱讀
- Python 教學(系列目錄)
- Python requests 網路請求
- Python JSON 與 CSV
- Python List Comprehension
- Python 串接 OpenAI API(下一篇)