Python中的多处理:网页抓取并没有加快速度

时间:2014-11-14 07:56:41

标签: python web-scraping multiprocessing

我想使用多处理模块加速网页抓取。 我的目标是在页面中提取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))

如何修改它以赋予它多处理的全部功能?谢谢。

1 个答案:

答案 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,那么你的线程池太小了。