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

为什么Python中使用concurrent.futures搭配BS4没有优化运行速度?

问题原因分析
  • executor.map的传参逻辑错误
    executor.map(func, iterable) 会将可迭代对象的每个元素单独作为参数传入目标函数执行。你当前代码将page_list直接传入map,相当于每次给get_url传的是单个URL字符串,而函数内部还在遍历data参数,就会遍历单个字符串的每个字符,发起的请求自然无效,最终url_list没有结果。单独调用get_url(page_list)时你传入的是完整的URL列表,遍历逻辑正常所以能拿到结果。
  • 代码缺少必要依赖导入
    你使用了requests.get但代码开头没有导入requests库,运行时会抛出导入异常。
  • submit方法无提速的核心原因
    大概率是你在每次调用submit后立刻调用了.result()方法,相当于提交一个任务就阻塞等待结果,本质还是串行执行,没有用到多线程的并发能力。
  • 全局变量的使用不规范
    多线程场景下尽量避免直接操作全局变量,虽然Python列表的append是原子操作不会出现数据竞争,但代码可读性和可维护性很差,更推荐让每个线程返回自己抓取的结果,最后统一合并。
修正后的代码示例
# 导入所有必要依赖
import requests
import concurrent.futures
from bs4 import BeautifulSoup

def page_builder(amount): 
    page_list = []
    for i in range(1, amount):
        url = 'https://quotes.toscrape.com/page/' + str(i) + '/'
        page_list.append(url)
    print('---- URL LIST SUCCESSFULLY CREATED ----')
    return page_list

# 修改为接收单个URL,返回当前页面抓取的作者列表
def get_url(url):
    try : 
        r = requests.get(url)
        soup = BeautifulSoup(r.content, 'html.parser')
        titles = soup.find_all("small", {"class": "author"})
        return [title.text for title in titles]
    except Exception as e:
        print(f"Issue is --> {e}")
        return []

page_list = page_builder(10)
url_list = []

with concurrent.futures.ThreadPoolExecutor() as executor :
    # map返回的是每个函数执行的结果迭代器,直接遍历合并即可
    for result in executor.map(get_url, page_list):
        url_list.extend(result)

print(url_list)

如果要使用submit方法,正确的并发写法如下:

with concurrent.futures.ThreadPoolExecutor() as executor:
    # 先提交所有任务,不阻塞等待结果
    futures = [executor.submit(get_url, url) for url in page_list]
    # 统一等待任务完成后收集结果
    for future in concurrent.futures.as_completed(futures):
        url_list.extend(future.result())

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 05:36:02