Python requests+threading爬取特定站点多线程失效问题咨询
可能的原因
- 目标站点服务端限流:pikabu这类公共社区站点普遍配置了基于IP的请求频率限制规则,短时间内收到同一IP的大量并发请求后,会对超额请求做延迟响应、丢弃处理甚至直接拉黑,你看到的阶梯式耗时就是服务端队列延迟的典型表现。你的测试站点没有配置频率限制,所以多线程效果符合预期。
- urllib3默认同域名连接数限制:requests底层依赖的urllib3库,默认对同一域名最多仅允许2个并发连接,你发起的18个请求全部指向pikabu.ru域名,即使开了18个线程,大部分请求也会在本地等待连接释放,实际并发数只有2,表现和串行几乎一致。
- 请求特征不完整被风控拦截:你当前仅配置了User-Agent头,缺少Referer、Cookie等正常浏览器请求会携带的字段,站点的风控系统会识别到异常请求,主动降低响应优先级甚至返回超时,这也是你设置5秒超时后大量请求失败的原因。
可落地的优化方案
- 调整连接池配置:自定义requests Session并手动调高同域名连接数上限,示例代码如下:
import requests from requests.adapters import HTTPAdapter session = requests.Session() # 同域名最大并发连接数调整为10 session.mount('https://pikabu.ru', HTTPAdapter(pool_connections=10, pool_maxsize=10)) # 后续请求用session.get代替requests.get即可
- 控制并发数量:不要一次性启动全部线程,改用
concurrent.futures.ThreadPoolExecutor控制同时运行的线程数为3~5,规避站点限流规则,示例如下:
from concurrent.futures import ThreadPoolExecutor # 最大并发数设为4 with ThreadPoolExecutor(max_workers=4) as executor: for idx, page in enumerate(pikabu_urls): executor.submit(Pikabu_Downloader(url=page, name=str(idx)).run)
- 完善请求特征:提前通过浏览器访问目标站点获取有效Cookie、添加对应页面的Referer头,模拟正常用户的请求行为,降低被风控拦截的概率。
- 可选优化:IO密集型场景下改用异步请求方案(如aiohttp+asyncio),比多线程资源开销更低、并发效率更高。
内容的提问来源于stack exchange,提问作者MaxD
相关产品推荐
相关产品推荐

