影刀RPA Python多线程加速:让采集速度提升10倍的实战方案

影刀RPA Python多线程加速:让采集速度提升10倍的实战方案

作者:林焱

用requests采集数据,一次请求0.3秒,1000个URL就是300秒(5分钟)。但如果你开10个线程同时请求,同样1000个URL只需要30秒。

这就是多线程的核心价值。影刀的流程是单线程执行,但Python代码块里可以开多线程——这篇文章讲清楚怎么安全地加速你的采集流程。

什么时候需要多线程?

并不是所有场景都适合多线程。先判断你的场景:

  • 适合多线程:每个请求相互独立(比如采集1000个商品详情页)、请求之间有大量IO等待、不需要共享状态
  • 不适合多线程:请求之间有依赖关系(比如先登录再操作)、需要严格按顺序处理、目标网站有并发限制

店群矩阵自动化突破运营极限!

最简单的多线程模板

importrequestsfromconcurrent.futuresimportThreadPoolExecutor,as_completeddeffetch_one(url):"""单个URL的采集逻辑"""try:headers={"User-Agent":"Mozilla/5.0 ..."}resp=requests.get(url,headers=headers,timeout=10)ifresp.status_code==200:return{"url":url,"data":resp.text[:100]}else:return{"url":url,"error":f"状态码{resp.status_code}"}exceptExceptionase:return{"url":url,"error":str(e)}# 要采集的URL列表urls=[f"https://example.com/product/{i}"foriinrange(1,101)]# 开10个线程并发采集results=[]withThreadPoolExecutor(max_workers=10)asexecutor:# 提交所有任务futures={executor.submit(fetch_one,url):urlforurlinurls}# 按完成顺序收集结果forfutureinas_completed(futures):results.append(future.result())

ThreadPoolExecutor是Python内置的线程池,不需要额外安装。max_workers=10表示最多10个线程同时跑。as_completed会按任务完成顺序返回结果(谁先完先拿谁的结果,不等慢的)。

控制并发量,避免被封

开线程一时爽,但开太多会导致:

  • IP被封(一分钟发几百个请求)
  • 服务器返回429(Too Many Requests)
  • 内存爆掉

安全方案:线程数 + 延时 + 重试

importtimeimportrandomfromconcurrent.futuresimportThreadPoolExecutordefsafe_fetch(url,retry=3):forattemptinrange(retry):try:time.sleep(random.uniform(0.5,1.5))# 随机延时resp=requests.get(url,timeout=10)ifresp.status_code==200:returnresp.json()elifresp.status_code==429:# 被限速wait=5*(attempt+1)print(f"被限速,等待{wait}秒后重试...")time.sleep(wait)else:returnNoneexceptExceptionase:ifattempt==retry-1:returnNonetime.sleep(2)returnNoneurls=[...]# 你的URL列表results=[]withThreadPoolExecutor(max_workers=5)asexecutor:# 别开太多,5个就够了futures={executor.submit(safe_fetch,url):urlforurlinurls}forfutureinas_completed(futures):result=future.result()ifresult:results.append(result)

把结果写回影刀变量

多线程的结果是Python的列表/字典,直接存到影刀的变量里就行:

# 多线程采集完后,results是一个列表# 影刀里可以直接用这个变量写入Excel、发邮件等

如果你需要在采集过程中实时写Excel,注意:openpyxl不是线程安全的,多线程同时写会出问题。正确做法是:采集线程只负责获取数据,全部采集完之后,在单线程里统一写入Excel。

踩坑实录

temu店群自动化报活动案例

坑1:多线程下的异常被吞掉

executor.submit()提交的任务如果抛异常,不会立即报错,只有你调用future.result()时才会抛出。所以必须在result()那里用try/except包住。

坑2:变量作用域混乱

在多线程函数里修改全局变量会导致数据错乱。正确的做法是每个线程返回自己的结果,最后由主线程汇总。不要在多线程里修改共享变量。

坑3:requests.Session不是线程安全的

不能用一个Session对象在多个线程间共享。每个线程应该用自己的requests调用。如果一定要用Session,可以在每个线程的函数里创建独立的Session:

deffetch_one(url):session=requests.Session()# 每个线程独立的Sessionresp=session.get(url)session.close()returnresp.json()

坑4:线程数开太多反而更慢

Python因为有GIL(全局解释器锁),多线程主要适合IO密集型任务(网络请求、文件读写)。对于计算密集型任务,多线程几乎没有加速效果。而且线程数超过CPU核心数之后,上下文切换开销会拖慢整体速度。一般来说,max_workers设置在5-20之间比较合理。

写在最后

多线程是采集提速的最简单方案。但记住:快不是目的,稳定才是。采集流程跑崩了比跑慢了更糟糕。永远先保证单线程跑通,再逐步加线程数,一边加一边观察目标网站的响应——合理的并发数是"再快就要被封了"的那个临界点。