跨多个进程分发python工作负载

时间:2012-05-18 23:42:58

标签: python multiprocessing

让我们假设我想在Google搜索“hello”这个词。然后,我想转到Google前100页的每个链接,下载该链接页面的HTML。由于每页有10个结果,这意味着我必须点击大约1,000个链接。

这就是我用一个过程来做的事情:

from selenium import webdriver
driver=webdriver.Firefox()
driver.get('http://google.com')

# do the search
search = driver.find_element_by_name('q')
search.send_keys('hello')
search.submit()

# click all the items
links_on_page = driver.find_elements_by_xpath('//li/div/h3/a')
for item in links_on_page:
    item.click()
    # do something on the page
    driver.back()

# go to the next page
driver.find_element_by_xpath('//*[@id="pnnext"]')

这显然需要很长时间才能在100页上完成。我如何分配负载,以便我可以(例如)打开三个驱动程序,每个驱动程序将“检出”一个页面。例如:

  • 驱动程序#1检出第1页。开始第1页。
  • 驱动程序#2看到第1页已签出并转到第2页。从第2页开始。
  • 驱动程序#3看到第1页已检出并转到第2页。与第2页相同。从第3页开始。
  • 1号司机完成了第1页的工作...开始第4页。

我理解这将如何工作的原理,但实际的代码是什么才能实现这个工作的基本实现?

2 个答案:

答案 0 :(得分:0)

您可能想要使用multiprocessing Pool。为此,请编写一个按页码参数化的方法:

def get_page_data(page_number):
    # Fetch page data
    ...
    # Parse page data
    ...
    for linked_page in parsed_links:
        # Fetch page source and save to file
        ...

然后只使用你认为合适的许多过程的Pool(确定这个数字可能需要一些实验):

from multiprocessing import Pool

if __name__ == '__main__':
    pool = Pool(processes=4)
    pool.map(get_page_data, range(1,101))

现在将设置4个进程,每个进程从Google获取一个页面,然后获取它链接到的每个页面。

答案 1 :(得分:0)

不直接回答您的问题,但提出可能使您的代码在单个进程中可用的途径,从而避免不同线程/进程之间的同步问题......

您可能最好使用Twisted这样的框架来启用异步网络操作,以便将所有操作保持在同一个进程中。在您的代码中,HTML代码的解析可能比获取页面所需的完整网络操作花费的时间少得多。因此,使用异步IO,您可以同时启动几个请求,并仅在响应到达时解析结果。实际上,每次返回页面时,您的进程很可能在runloop中“空闲”。