CodeGym /课程 /Python SELF ZH /网页爬取中的错误处理

网页爬取中的错误处理

Python SELF ZH
第 32 级 , 课程 4
可用

如果你已经看到这节课,说明你已经对网页爬取的工作原理有了一定的了解, 并且知道如何使用强大的BeautifulSoup从HTML中提取所需的数据。 不过,网页爬取的世界并不像教科书写得那么顺利。有时候,想要获取数据的 美好梦想可能会变成与各种错误作斗争的噩梦。所以,让我们聊聊如何避开这些 潜在的坑,并让我们的爬虫尽可能稳定。

1. 网页爬取中的常见错误

404错误和其他HTTP错误

经典问题:你尝试获取一个网页,却收到一条自豪的“404 Not Found”。 这可能是因为网页被删除或移动了。其他常见的HTTP错误包括403(Forbidden), 500(Internal Server Error)和503(Service Unavailable)。

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()  # 引发错误的HTTP响应
    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被封了,就换用下一个代理。如果网站挂了,那就先爬取别的页面。 如果页面中某些原本应该存在的元素不见了,可以通知爬虫的拥有者更新解析脚本并发送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