You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

requests-futures爬虫速度过慢问题排查及高性能替代方案咨询

解决requests-futures爬虫速度过慢的问题 & 高性能替代工具推荐

先分析你当前代码的几个关键问题,这些是导致速度慢的主要原因,然后再聊替代方案:

一、修复当前requests-futures代码的问题

你的爬取速率只有0.5个请求/秒,和as_completed关系不大,反而代码里有几个明显的错误和优化点:

1. 多进程调用的致命错误

你这段代码里创建了multiprocessing.Process但没有调用start(),等于这些进程根本没运行,所有的解析任务都没执行,还白白消耗了资源。另外,在ThreadPool的线程里再开多进程完全没必要——解析HTML是CPU轻量型任务,直接在线程里处理就好,多进程的进程间通信反而会增加开销。

把这部分改成直接调用:

try:
    main_func(resp)
except requests.exceptions.JSONDecodeError:
    logging.warning("[requests.custom.debug]: JSONDecodeError when parsing response")

或者更高效的方式是用FuturesSession的回调函数,让请求完成后自动触发解析,不用在as_completed里等待:

def handle_response(resp, *args, **kwargs):
    try:
        main_func(resp)
    except requests.exceptions.JSONDecodeError:
        logging.warning("[requests.custom.debug]: JSONDecodeError when parsing response")
    finally:
        resp.close()

# 创建session的时候绑定回调
with FuturesSession(executor=ThreadPoolExecutor(max_workers=16)) as session:
    for url in url_list:
        proxy = random.choice(proxy_list).replace("https:/", "http:/")
        session.get(url,
                   proxies={'http': proxy, 'https': proxy},  # 同一个代理,避免重复连接
                   headers={
                       'User-Agent': str(ua.chrome),
                       'Accept': '*/*',
                       'Accept-Encoding': 'gzip, deflate, br',
                       'Connection': 'keep-alive',
                       'Content-Type': 'text/plain;charset=UTF-8',
                   },
                   timeout=10,  # 关键:设置超时,防止请求挂起
                   hooks={'response': handle_response})

2. 代理选择的优化

你之前给http和https各随机选一个代理,这会导致每个请求建立两个不同的连接,大大增加了TCP握手的开销。应该给同一个请求用同一个代理,减少连接建立的时间。

3. 增加超时与重试机制

没有设置timeout的话,某个请求卡住会拖慢整个线程池的效率。另外,添加重试机制可以处理临时的网络错误或代理失效:

from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

# 配置重试
retry_strategy = Retry(
    total=3,
    backoff_factor=1,
    status_forcelist=[429, 500, 502, 503, 504],
    allowed_methods=["GET"]
)
adapter = HTTPAdapter(max_retries=retry_strategy)

with FuturesSession(executor=ThreadPoolExecutor(max_workers=16)) as session:
    session.mount("http://", adapter)
    session.mount("https://", adapter)
    # 后续请求代码...

4. 调整线程池大小

max_workers=8可能太小了,你可以尝试增加到16或32(根据目标网站的反爬强度调整,不要一下子设得太大,避免被封)。

二、比requests-futures性能更出色的替代工具

如果优化后还是达不到预期速度,这些工具的性能会更优:

1. aiohttp(异步HTTP客户端)

基于asyncio的异步HTTP库,是单线程异步模型,没有线程切换的开销,并发量可以轻松达到数百甚至上千,适合高并发爬取。示例代码框架:

import asyncio
import aiohttp

async def fetch(session, url, proxy):
    try:
        async with session.get(url, proxy=proxy, timeout=10) as resp:
            html = await resp.text()
            main_func(html)  # 这里可以直接处理解析
    except Exception as e:
        logging.warning(f"Error fetching {url}: {e}")

async def main():
    connector = aiohttp.TCPConnector(limit=100)  # 控制并发连接数
    async with aiohttp.ClientSession(connector=connector, headers=your_headers) as session:
        tasks = []
        for url in url_list:
            proxy = random.choice(proxy_list)
            tasks.append(fetch(session, url, proxy))
        await asyncio.gather(*tasks)

if __name__ == "__main__":
    asyncio.run(main())

2. httpx

支持同步和异步两种模式,API设计和requests几乎一致,学习成本低,性能和aiohttp接近,还支持HTTP/2,适合现代网站的爬取。

3. Scrapy

专为大规模爬虫设计的框架,自带并发调度、去重、重试、反爬处理等功能,适合需要爬取大量页面的场景。它的底层是基于Twisted异步框架,性能非常出色,而且扩展性强,可以轻松添加中间件处理代理、UA池等。

总结

先修复当前代码中的错误(尤其是多进程没start、代理选择、超时设置),调整线程池大小,应该能大幅提升爬取速度。如果还是需要更高的并发,优先考虑aiohttp或httpx的异步模式,大规模爬取则选Scrapy。

内容的提问来源于stack exchange,提问作者Coder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 14:28:11