如何限制Python爬虫请求速率 解决HTTP 429请求过多报错
爬取429限流问题解决方案
触发无Retry-After头的HTTP 429报错,本质是请求频率、请求特征触发站点反爬限流,可通过以下修改直接解决:
1. 基础修复:添加随机请求间隔
最直接的限流方式是在两次请求之间加入随机等待时长,避免匀速高频请求被反爬规则识别,不要使用固定间隔,加随机浮动更贴近真实用户访问行为。
首先导入依赖:
import time import random
修改原有爬取循环逻辑,同时优化DataFrame合并逻辑(原df.append方法已在新版Pandas中移除,逐行追加效率极低,改用列表暂存后一次性合并性能提升明显):
def save_table(urls): df_list = [] writer = pd.ExcelWriter(<address>, engine = 'xlsxwriter') for idx, url in enumerate(urls): # 每次请求前等待1~3秒随机时长,若仍触发限流可将区间调整为2~5秒 time.sleep(random.uniform(1, 3)) try: soup = return_html_soup(url) temp_table = some_function(soup) df_list.append(temp_table) print(f"爬取进度:{idx+1}/{len(urls)}") except Exception as e: print(f"链接{url}爬取失败,错误信息:{str(e)},跳过该链接后续可补爬") continue # 一次性合并所有临时表 df = pd.concat(df_list, ignore_index=True) df.to_excel(writer, sheet_name=<some name>) writer.close()
2. 进阶优化:添加指数退避重试机制
如果偶尔触发429导致任务中断,可以加入自动重试逻辑,遇到限流错误时自动延长等待时间后重试,无需人工重启任务。
先安装重试依赖:pip install tenacity
修改页面请求函数return_html_soup,加入重试规则和真实请求头(很多站点默认拦截爬虫默认UA,哪怕请求频率不高也会报429):
import requests from bs4 import BeautifulSoup from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type @retry( stop=stop_after_attempt(5), # 单链接最多重试5次 wait=wait_exponential(multiplier=1, min=2, max=30), # 指数退避等待:2s、4s、8s...最长等待30s retry=retry_if_exception_type((requests.exceptions.HTTPError, requests.exceptions.Timeout, requests.exceptions.ConnectionError)) ) def return_html_soup(url): # 替换为真实浏览器UA,不要使用requests默认标识 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36" } resp = requests.get(url, headers=headers, timeout=15) # 状态码为4xx/5xx时主动抛异常触发重试 resp.raise_for_status() return BeautifulSoup(resp.text, "html.parser")
补充注意点
- 若站点限流严格,可将请求间隔调整为36秒,或每爬取50个页面后额外休息12分钟,数百个页面总耗时仅十几分钟,远低于被封IP后换IP重跑的成本
- 不要使用固定间隔等待,固定间隔非常容易被反爬规则匹配识别为爬虫
- 原有代码中
writer.save()无需单独调用,新版Pandas执行writer.close()时会自动完成文件写入保存
内容的提问来源于stack exchange,提问作者Vuotelin
相关产品推荐
相关产品推荐

