載入中…
載入中…
運用 requests 與 BeautifulSoup 抓取網頁資料,搭配 Selenium 處理動態網頁,並將資料存入 CSV 或資料庫。
每章講義 PDF 可免費線上預覽;範例程式碼與打包下載請進入各章節頁。
講義教材整理中,敬請期待。
撰寫一個函式 check_urls(urls),接受一個網址列表,回傳每個網址的 HTTP 狀態碼字典。需要處理網路錯誤與逾時。
使用 requests.get(url, timeout=5) 並包裹在 try/except 中。
import requests
def check_urls(urls):
"""接受網址列表,回傳 {網址: 狀態碼或錯誤訊息} 字典"""
results = {}
for url in urls:
try:
# timeout=5 秒,避免網站沒回應導致程式卡住
response = requests.get(url, timeout=5)
results[url] = response.status_code
except requests.exceptions.Timeout:
results[url] = "逾時"
except requests.exceptions.RequestException as e:
# 涵蓋連線錯誤、DNS 解析失敗等其他網路例外
results[url] = f"錯誤:{e}"
return results
if __name__ == "__main__":
urls = [
"https://www.python.org",
"https://www.google.com",
"https://this-domain-does-not-exist-abc123.com",
]
status_map = check_urls(urls)
for url, status in status_map.items():
print(f"{url} -> {status}")
爬取 PTT 某個版(如 Python 版)的最新 20 篇文章標題與作者,並存成 CSV 檔案。需要處理已刪除文章的情況。
注意 PTT 需要設定 Cookie 才能存取 18+ 版面,可以先用 Python 版練習。
import csv
import requests
from bs4 import BeautifulSoup
BOARD_URL = "https://www.ptt.cc/bbs/Python/index.html"
# PTT 會檢查是否已通過 18 歲同意頁,設定 cookie 避免被導去同意頁
COOKIES = {"over18": "1"}
def fetch_articles(url):
"""爬取單一頁面的文章標題與作者,回傳 list of dict"""
resp = requests.get(url, cookies=COOKIES, timeout=5)
resp.raise_for_status()
soup = BeautifulSoup(resp.text, "html.parser")
articles = []
for entry in soup.select("div.r-ent"):
title_tag = entry.select_one("div.title a")
# 已刪除的文章沒有 <a> 標籤,title 會顯示「本文已被刪除」
if title_tag is None:
title = "(已刪除)"
author = "(未知)"
else:
title = title_tag.text.strip()
author_tag = entry.select_one("div.meta div.author")
author = author_tag.text.strip() if author_tag else "(未知)"
articles.append({"title": title, "author": author})
return articles
def main():
articles = fetch_articles(BOARD_URL)[:20]
with open("ptt_python_board.csv", "w", newline="", encoding="utf-8-sig") as f:
writer = csv.DictWriter(f, fieldnames=["title", "author"])
writer.writeheader()
writer.writerows(articles)
print(f"共爬取 {len(articles)} 篇文章,已存成 ptt_python_board.csv")
if __name__ == "__main__":
main()
爬取某電商網站商品列表的前 5 頁,收集商品名稱、價格、評分,計算最高/最低/平均價格,並輸出統計報告。
分析 URL 的換頁規律,加入隨機延遲,用 pandas DataFrame 管理資料並計算統計值。
import time
import random
import requests
import pandas as pd
from bs4 import BeautifulSoup
# 假設商品列表頁的換頁規律是 ?page=N(依實際網站調整)
BASE_URL = "https://example-shop.com/products?page={}"
HEADERS = {"User-Agent": "Mozilla/5.0"}
def fetch_page(page: int):
"""爬取單一頁的商品資料,回傳 list of dict"""
url = BASE_URL.format(page)
resp = requests.get(url, headers=HEADERS, timeout=5)
resp.raise_for_status()
soup = BeautifulSoup(resp.text, "html.parser")
products = []
for item in soup.select(".product-item"):
name_tag = item.select_one(".product-name")
price_tag = item.select_one(".product-price")
rating_tag = item.select_one(".product-rating")
if not (name_tag and price_tag):
continue
# 價格文字可能含「$」「,」等符號,需清理後轉數字
price_text = price_tag.text.strip().replace("$", "").replace(",", "")
products.append({
"name": name_tag.text.strip(),
"price": float(price_text),
"rating": float(rating_tag.text.strip()) if rating_tag else None,
})
return products
def main():
all_products = []
for page in range(1, 6): # 前 5 頁
all_products.extend(fetch_page(page))
# 加入隨機延遲,避免對伺服器造成負擔或被判定為機器人
time.sleep(random.uniform(1, 2))
df = pd.DataFrame(all_products)
print("=== 商品統計報告 ===")
print(f"總商品數:{len(df)}")
print(f"最高價格:{df['price'].max():.0f}")
print(f"最低價格:{df['price'].min():.0f}")
print(f"平均價格:{df['price'].mean():.2f}")
df.to_csv("products_report.csv", index=False, encoding="utf-8-sig")
print("已輸出 products_report.csv")
if __name__ == "__main__":
main()