我想使用多处理模块加速网页抓取。 我的目标是在页面中提取HTML的一部分并将其保存在父变量中。 最后,将该变量写入文件。
但我遇到的问题是处理页面大约需要1秒钟。
我的代码有效,但它不能满足我的需求:
import urllib.request
from bs4 import BeautifulSoup
from multiprocessing.dummy import Pool # This is a thread-based Pool
from multiprocessing import cpu_count
def parseWeb(url):
page = urllib.request.urlopen(url)
soup = BeautifulSoup(page)
h2_tag = soup.find('h2', class_='midashigo')
return h2_tag
if __name__ == '__main__':
file = 'links.txt' # each link is on a separate line.
pool = Pool(cpu_count() * 2)
with open(file, 'r') as f:
results = pool.map(parseWeb, f)
with open('output.txt', 'w', encoding='utf-8') as w:
w.write(str(results))
如何修改它以赋予它多处理的全部功能?谢谢。
答案 0 :(得分:4)
这个过程应该是I / O绑定的,这意味着你的瓶颈应该是在解析之前可以拉下连接的数量,但实际上它可能会被CPU或内存限制。
您需要意识到的第一件事是多线程/处理不会加快单个页面解析时间。因此,如果一个页面需要一秒钟而你有420000页面则需要420000秒。如果您将线程数增加到您的PC有两倍的内核数量并且您的PC有4个内核,那么每个页面将有8个线程运行1秒。你仍然以420000/8秒结束,这是875分钟(实际上这不完全正确),这是14.5个小时的处理....
对于可管理的时间跨度,您将需要大约400个线程,这将使处理时间缩短到理论上的17分钟。
运行这么多线程并解析页面内存也会成为一个问题。
我把这个小应用程序拼凑起来进行了一些测试
from time import sleep
from multiprocessing.dummy import Pool
from multiprocessing import cpu_count
def f(x):
sleep(1)
x = int(x)
return x *x
if __name__ == '__main__':
pool = Pool(cpu_count() * 100)
with open('input.txt', 'r') as i:
results = pool.map(f, i)
with open('output.txt', 'w') as w:
w.write(str(results))
输入文件的编号为1到420 000,处理时间为1053.39秒(大约17.5分钟),但这并不能说明你需要多长时间,因为提到的内存和我/ O绑定问题,你最终会得到一些明显变慢的东西。
最重要的是,如果你没有最大化你的CPU或RAM或网络I / O,那么你的线程池太小了。