iT邦幫忙

2026 iThome 鐵人賽

DAY 3
0
自我挑戰組

Python 爬蟲與資料分析實戰:從網路資料到資訊視覺化系列 第 11 篇

Day 11|Python 爬蟲實戰:突破單頁限制,使用 Requests 與 BeautifulSoup 爬取多頁資料

  • 分享至 

  • xImage
  •  

一、認識網頁分頁的運作方式

在很多網站中,當資料量太大時,通常不會一次顯示所有內容,而是將資料拆分成多個頁面。

例如:

第 1 頁:書籍 1~20

第 2 頁:書籍 21~40

第 3 頁:書籍 41~60

如果想要取得所有資料,就必須讓程式依序訪問這些頁面。

Books to Scrape 的分頁網址有一個特點:每一頁的網址都會包含頁碼。

例如:

第一頁:

https://books.toscrape.com/

第二頁:

https://books.toscrape.com/catalogue/page-2.html

第三頁:

https://books.toscrape.com/catalogue/page-3.html

從網址可以發現,第一頁沒有直接使用 page-1.html,而是使用網站首頁;第二頁開始才使用 page-2.html、page-3.html 這樣的格式。

因此,在設計爬蟲時,必須先了解網站的分頁規則,才能正確組合每一頁的網址。

二、實作一:先確認第二頁的網址是否能正常取得

在開始撰寫多頁面爬蟲之前,先確認第二頁的網址可以正常存取。

import requests

url = "https://books.toscrape.com/catalogue/page-2.html"

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

print("狀態碼:", response.status_code)
print(response.url)

這裡使用 requests.get() 發送 GET 請求,並透過 status_code 確認伺服器是否成功回傳資料。

如果狀態碼是 200,代表請求成功。

接著可以使用 BeautifulSoup 解析第二頁的 HTML。

from bs4 import BeautifulSoup

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

books = soup.select("article.product_pod")

print("第二頁書籍數量:", len(books))

如果能成功取得書籍區塊,就代表第二頁也可以使用昨天學過的方法進行解析。

這個步驟很重要,因為在正式進行多頁面爬蟲之前,先確認網址規則和 HTML 結構,可以避免後續出現大量錯誤。

三、實作二:使用 for 迴圈自動切換頁面

前面已經確認第二頁的網址規則,接下來就可以利用 for 迴圈自動產生不同頁面的網址。

這次先設定抓取前 5 頁。

for page in range(1, 6):

if page == 1:
    url = "https://books.toscrape.com/"
else:
    url = f"https://books.toscrape.com/catalogue/page-{page}.html"

print("目前抓取頁面:", url)

這段程式碼會依序產生第一頁到第五頁的網址。

這裡使用 range(1, 6),是因為 Python 的 range() 不包含結束值,因此實際產生的數字是 1、2、3、4、5。

另外,第一頁和其他頁面的網址格式不同,所以使用 if...else 進行判斷。

這樣就能自動產生不同頁面的網址,不需要手動修改每一次的 URL。

四、實作三:建立多頁面爬蟲,抓取所有書籍資料

接下來要將昨天的書籍資料擷取程式與今天的分頁邏輯整合起來。

這次會抓取前 5 頁的書籍資料,並將所有資料存放在同一個 List 中。

import requests
from bs4 import BeautifulSoup

books_data = []

rating_map = {
"One": 1,
"Two": 2,
"Three": 3,
"Four": 4,
"Five": 5
}

for page in range(1, 6):

if page == 1:
    url = "https://books.toscrape.com/"
else:
    url = f"https://books.toscrape.com/catalogue/page-{page}.html"

print("正在抓取第", page, "頁")

response = requests.get(url, timeout=10)
response.raise_for_status()

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

books = soup.select("article.product_pod")

for book in books:

    title = book.select_one("h3 a")["title"]

    price_text = book.select_one(".price_color").text
    price = float(price_text.replace("£", ""))

    availability = book.select_one(".availability").text.strip()

    rating_text = book.select_one(".star-rating")["class"][1]
    rating = rating_map[rating_text]

    book_info = {
        "title": title,
        "price": price,
        "availability": availability,
        "rating": rating,
        "page": page
    }

    books_data.append(book_info)

print("全部抓取完成!")
print("總共取得", len(books_data), "筆書籍資料")
程式碼解說

這段程式碼可以分成三個部分。

第一部分:切換頁面

透過 for page in range(1, 6) 依序取得第一頁到第五頁的網址。

第二部分:解析 HTML

使用 Requests 取得網頁內容,再透過 BeautifulSoup 找出每一頁的書籍區塊。

第三部分:整理資料

使用內層的 for 迴圈逐本處理書籍,將名稱、價格、庫存和評分整理成 Dictionary,再加入 books_data。

這裡額外增加了一個 page 欄位,用來記錄每本書來自哪一頁。

這樣做的好處是,後續如果發現某筆資料有問題,就能知道它是從哪個頁面抓取的。

另外,response.raise_for_status() 可以在 HTTP 請求失敗時拋出例外,避免程式在取得錯誤頁面後繼續執行。

五、實作四:確認多頁面資料是否正確

完成多頁面爬蟲後,接下來要確認資料是否真的成功整合。

首先,查看總筆數。

print("總資料筆數:", len(books_data))

如果網站每頁有 20 本書,前 5 頁正常情況下應該會取得 100 筆資料。

接著,查看前 5 筆資料。

for book in books_data[:5]:
print(book)

也可以查看最後 5 筆資料。

for book in books_data[-5:]:
print(book)

這樣可以確認資料不只來自第一頁,而是已經成功累積多個頁面的內容。

最後,統計每一頁抓取到的資料筆數。

for page in range(1, 6):

page_books = [
    book for book in books_data
    if book["page"] == page
]

print("第", page, "頁:", len(page_books), "本書")

透過這個方式,可以確認每一頁是否都有成功取得資料。

六、實作五:分析多頁面書籍資料

完成多頁面資料擷取後,就可以利用昨天學過的分析方式,對更多資料進行整理。

  1. 計算所有書籍的平均價格
    total_price = sum(book["price"] for book in books_data)

average_price = total_price / len(books_data)

print("平均價格:", round(average_price, 2))

這段程式碼會加總所有書籍的價格,再除以總筆數,計算出平均價格。

  1. 找出價格最高的書籍
    most_expensive = max(
    books_data,
    key=lambda book: book["price"]
    )

print("價格最高的書籍:", most_expensive["title"])
print("價格:", most_expensive["price"])

這裡使用 max() 找出價格最高的書籍,與昨天使用的 min() 概念相同,只是比較方向不同。

  1. 篩選五星評分的書籍
    five_star_books = [
    book for book in books_data
    if book["rating"] == 5
    ]

print("五星書籍數量:", len(five_star_books))

for book in five_star_books[:10]:
print(book["title"], book["price"])

這段程式碼會找出所有評分為 5 的書籍,並顯示前 10 筆結果。

透過多頁面爬蟲,我們就能取得比單頁更多的資料,進一步進行篩選和分析。

七、實作六:將多頁面資料儲存成 CSV

當資料量增加後,將資料儲存成 CSV 就更加重要。

這次會將前 5 頁的書籍資料全部寫入同一個 CSV 檔案。

import csv

with open("books_all_pages.csv", "w", newline="", encoding="utf-8-sig") as file:

fieldnames = [
    "title",
    "price",
    "availability",
    "rating",
    "page"
]

writer = csv.DictWriter(file, fieldnames=fieldnames)

writer.writeheader()
writer.writerows(books_data)

print("多頁面資料已經儲存完成")

這裡使用 csv.DictWriter() 將 List 中的 Dictionary 寫入 CSV。

由於資料已經整合在同一個 List 裡,因此不需要為每一頁建立不同的檔案,只要在最後統一寫入即可。

在 Google Colab 中,可以透過以下程式碼下載檔案:

from google.colab import files

files.download("books_all_pages.csv")

這樣就能將多頁面爬取的資料下載到自己的電腦,之後也可以使用 Excel 或 Pandas 進行分析。

八、實作七:加入錯誤處理,避免爬蟲中斷

實際執行爬蟲時,可能會遇到網路連線失敗、伺服器回傳錯誤狀態碼,或是網頁結構發生變化等情況。

如果沒有處理這些問題,程式可能會在某一頁發生錯誤後直接停止。

因此,可以使用 try...except 來處理請求錯誤。

import requests
from bs4 import BeautifulSoup

url = "https://books.toscrape.com/catalogue/page-2.html"

try:
response = requests.get(url, timeout=10)
response.raise_for_status()

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

books = soup.select("article.product_pod")

print("成功取得", len(books), "本書籍")

except requests.exceptions.RequestException as e:
print("網頁請求失敗:", e)

這裡使用 try 執行可能發生錯誤的程式碼。

如果請求失敗,或伺服器回傳錯誤狀態碼,程式就會進入 except 區塊,顯示錯誤訊息,而不是直接中斷整個 Notebook。

不過,錯誤處理並不代表所有問題都能自動解決。如果網站的 HTML 結構改變,仍然需要重新檢查 CSS Selector 是否正確。


上一篇
Day 10|Python 爬蟲實戰:使用 Requests 與 BeautifulSoup 抓取書籍資料
下一篇
Day 12|Python 爬蟲實戰:自動偵測下一頁,完整抓取網站資料
系列文
Python 爬蟲與資料分析實戰:從網路資料到資訊視覺化 共 13 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言