CodeGym /Adesua ahorow /Python SELF TW /網頁抓取中的錯誤處理

網頁抓取中的錯誤處理

Python SELF TW
等級 32 , 課堂 4
開放

如果你已經看到這堂課,說明你對於網頁抓取原理以及如何使用優秀的 BeautifulSoup 從 HTML 中提取想要的數據已經有不錯的了解了。不過,在網頁抓取的世界中,可不是所有事情都像教材裡寫的那麼順利。有時候,想要收集資料的夢想可能會變成和錯誤奮鬥的噩夢。所以,讓我們來聊聊如何避開這些暗礁,讓我們的抓取工具盡可能穩健。

1. 網頁抓取中的常見錯誤

404 錯誤和其他 HTTP 錯誤

經典問題:你嘗試獲取某個頁面,但回應你的是自豪的 "404 Not Found"。這可能是因為該頁面已經刪除或者移動了。其他常見的 HTTP 錯誤還包括 403(Forbidden)、500(伺服器內部錯誤)和 503(服務不可用)。

HTML 結構的變化

你花了很多時間寫程式碼來提取數據,但隔天網站就稍微“打扮了一下”,更改了 HTML 結構。哎,又得重寫一遍了!

請求次數的限制

一些網站對大量的網頁抓取行為開始懷疑。有時候,最好的情況是暫時封鎖你,最壞的情況是永久封鎖。

等待時間和超時

有時候頁面載入得很慢,如果等待時間超出了預設的超時時間,腳本可能會崩潰。

2. 錯誤處理的方法

使用 try-except

你的腳本不應該因為一點小失誤就崩潰。加入 try-except 區塊可以捕捉錯誤,讓你的網頁抓取工具即使遇到問題也能繼續運作。

Python

    import requests
    from bs4 import BeautifulSoup
    
    url = 'http://example.com/some-nonexistent-page'
    
    try:
        response = requests.get(url)
        response.raise_for_status()  # 引發 HTTPError 對壞回應
    except requests.exceptions.HTTPError as errh:
        print("HTTP 錯誤:", errh)
    except requests.exceptions.ConnectionError as errc:
        print("連接錯誤:", errc)
    except requests.exceptions.Timeout as errt:
        print("超時錯誤:", errt)
    except requests.exceptions.RequestException as err:
        print("哦哦某些其他問題", err)
        

好的腳本不僅會捕獲異常,還會對每種錯誤類型有應對措施。被 IP 封鎖了 - 換個 proxy 繼續;網站掛掉了 - 你可以先抓取其他的。如果頁面中找不到某些應有的元素,可以通知網頁抓取工具的擁有者更新抓取腳本並發送 email。

日誌記錄

「為什麼要記錄日誌呢?」你可能會問。因為日誌是你的第二雙眼睛。它們可以幫助你快速找出問題並加以解決。

Python

import logging

logging.basicConfig(filename='scraper.log', level=logging.INFO)

try:
    # 你的網頁抓取程式
    pass
except Exception as e:
    logging.error("發生了例外情況", exc_info=True)
    

使用超時與重試

有時候,只需要等一下再試試看。這時可以用超時和重試來幫助。

Python

try:
    response = requests.get(url, timeout=5)
    response.raise_for_status()
except requests.exceptions.Timeout:
    print("超時錯誤發生了,重試中...")
    # 重試請求或執行其他操作
    

3. 穩健抓取的案例

帶有錯誤處理的簡單抓取工具

我們來寫一個小型但穩定的抓取工具,能處理一些常見的錯誤。

Python

import requests
from bs4 import BeautifulSoup
import time
import logging

logging.basicConfig(filename='scraper.log', level=logging.INFO)

url = 'http://example.com/some-nonexistent-page'

def fetch_html(url):
    try:
        response = requests.get(url, timeout=5)
        response.raise_for_status()
        return response.text
    except requests.exceptions.HTTPError as errh:
        logging.error("HTTP 錯誤: %s", errh)
    except requests.exceptions.ConnectionError as errc:
        logging.error("連接錯誤: %s", errc)
    except requests.exceptions.Timeout as errt:
        logging.warning("超時錯誤發生了,正在重試...")
        time.sleep(1)  # 等一等再試
        return fetch_html(url)
    except requests.exceptions.RequestException as err:
        logging.error("哦哦某些其他問題 %s", err)
    return None

html_content = fetch_html(url)
if html_content:
    soup = BeautifulSoup(html_content, 'html.parser')
    # 你的數據提取程式碼
else:
    print("未能取得頁面內容。")
    

部分保存數據

為了避免在意外發生時損失已經抓取到的數據,可以部分保存。例如,如果你從頁面列表中提取資料,邊提取邊保存結果,可以最大程度減少數據丟失的風險。

Python

import csv

def save_to_csv(data, filename='data.csv'):
    with open(filename, mode='a', newline='') as file:
        writer = csv.writer(file)
        writer.writerow(data)
    

因此,即使你的腳本在中途崩潰了,你也不會損失所有數據,並且可以從最後保存的狀態繼續。

你正在抓取的頁面可能會局部變化,大部分數據仍然可用。如果僅有小部分數據缺失,那麼放棄抓取並丟失寶貴的數據就不太划算了。

1
Опрос
資料提取,  32 уровень,  4 лекция
недоступен
資料提取
資料提取
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION