基于BeautifulSoup的网页爬虫错误处理:如何维持脚本持续运行
爬虫通用错误处理方案(持续运行版)
一、分类型捕获常见异常
爬虫运行中遇到的错误大多集中在网络请求、页面解析或文件操作环节,针对性捕获异常才能让脚本跳过错误继续执行:
- 请求类异常:捕获
requests.exceptions.InvalidSchema(无效协议)、requests.exceptions.ConnectionError(连接失败)、requests.exceptions.Timeout(请求超时)、requests.exceptions.HTTPError(HTTP错误码)等 - 解析类异常:捕获
AttributeError(解析时找不到节点)、UnicodeDecodeError(页面编码不兼容)等 - 文件操作异常:捕获
IOError(文件读写错误)、PermissionError(权限不足)等
二、给可恢复错误加重试机制
对于临时网络波动、服务器繁忙这类可恢复的错误,不要直接跳过,先重试几次再放弃:
- 设定重试次数(比如3次),每次重试前短暂休眠1-3秒,避免频繁请求触发反爬
- 仅对特定可恢复异常(如连接超时、5xx状态码)执行重试逻辑
三、记录错误日志
不要让错误悄无声息跳过,把错误URL、异常信息记录到日志文件,方便后续排查问题:
- 用Python内置
logging模块,或直接追加写入自定义错误日志文件
四、完整示例代码
import requests from bs4 import BeautifulSoup import time import logging # 配置错误日志 logging.basicConfig(filename='crawler_errors.log', level=logging.ERROR, format='%(asctime)s - %(levelname)s - %(message)s') def fetch_page(url, max_retries=3): retries = 0 while retries < max_retries: try: response = requests.get(url, timeout=10) response.raise_for_status() # 触发HTTP错误(如404、500) return response.text except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as e: retries += 1 time.sleep(2) if retries == max_retries: logging.error(f"重试{max_retries}次仍无法访问: {url}, 错误: {str(e)}") return None except requests.exceptions.InvalidSchema as e: logging.error(f"无效URL协议: {url}, 错误: {str(e)}") return None except requests.exceptions.HTTPError as e: logging.error(f"HTTP错误访问: {url}, 状态码: {response.status_code}, 错误: {str(e)}") return None except Exception as e: logging.error(f"未知错误访问: {url}, 错误: {str(e)}") return None def extract_links(html): if not html: return [] try: soup = BeautifulSoup(html, 'html.parser') return [a.get('href') for a in soup.find_all('a', href=True)] except Exception as e: logging.error(f"页面解析失败, 错误: {str(e)}") return [] def save_links(links, filename='links.txt'): try: with open(filename, 'a', encoding='utf-8') as f: for link in links: f.write(f"{link}\n") except (IOError, PermissionError) as e: logging.error(f"文件写入失败, 错误: {str(e)}") def main(urls): for url in urls: html = fetch_page(url) links = extract_links(html) if links: save_links(links) if __name__ == '__main__': target_urls = ['https://example.com', 'https://test.com'] # 替换为你的目标URL列表 main(target_urls)
关键说明
- 所有异常都会被捕获并记录到
crawler_errors.log,不会导致脚本终止 - 针对连接超时、网络波动这类问题自动重试3次,避免因临时错误中断
- 无效协议、HTTP错误码这类不可恢复的错误直接记录并跳过
- 解析和文件操作的错误也会被捕获,不影响后续URL处理
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

