使用多进程进行网页爬虫时如何让抓取结果与URL列表顺序一致
问题原因
- 多进程的执行顺序由操作系统调度决定,没有固定先后顺序,直接在子进程中追加结果到全局列表,自然会出现顺序随机的问题
- 额外隐含BUG:你当前写法里的全局变量
bonds_values在多进程场景下实际不共享,每个子进程会独立持有自己的变量副本,主进程最终无法拿到所有子进程的抓取结果
解决方案
multiprocessing.Pool.map()方法本身已经严格保证返回值的顺序和你传入的参数列表顺序完全一致,不需要额外做排序处理,只需要调整代码逻辑,让子进程把结果return出来,主进程接收返回值即可:
- 删掉全局变量
bonds_values的写入逻辑,修改worker函数直接返回抓取到的数值 - 主进程接收
p.map()的返回值,该返回值的顺序和bonds_url的顺序完全对应 - 可选优化:进程池数量不要设置为URL总数量,避免URL过多时系统资源占用过高,默认不传参数会自动使用和CPU核心数匹配的进程数,性能最优
修改后的完整代码
from requests_html import HTMLSession import constants from multiprocessing import Pool bonds_url = [] def f(url): session = HTMLSession() response = session.get(url) try: data = [i.text.strip() for i in response.html.find(".value")] res = float(data[0]) print(res) return res except: data = [i.text.strip() for i in response.html.find("div>span[data-reactid='31']")] res = float(data[0]) print(res) return res if __name__ == '__main__': with Pool() as p: # 返回的bonds_values顺序和bonds_url顺序完全一致 bonds_values = p.map(f, bonds_url) # 后续可直接按顺序使用bonds_values print(bonds_values)
如果你后续需要使用
imap_unordered这类不保证返回顺序的方法,也可以手动标记索引保证顺序:
- 传入参数改为
enumerate(bonds_url),每个任务拿到(原始索引, 对应url)- 子进程返回(原始索引, 抓取结果)
- 主进程收集所有结果后按索引排序,即可得到和原URL顺序一致的结果
内容的提问来源于stack exchange,提问作者Animesh Singh
相关产品推荐
相关产品推荐

