跨多个进程分发python工作负载
让我们假设我想在谷歌上搜索“你好”这个词。然后我想去谷歌前100页的每一个链接,下载链接页面的HTML。因为每页有10个结果,这意味着我必须点击大约1000个链接 这是我将如何使用单个流程完成的:跨多个进程分发python工作负载,python,multiprocessing,Python,Multiprocessing,让我们假设我想在谷歌上搜索“你好”这个词。然后我想去谷歌前100页的每一个链接,下载链接页面的HTML。因为每页有10个结果,这意味着我必须点击大约1000个链接 这是我将如何使用单个流程完成的: from selenium import webdriver driver=webdriver.Firefox() driver.get('http://google.com') # do the search search = driver.find_element_by_name('q') se
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页
我理解这将如何工作的原理,但实际的代码是什么才能实现这一工作的基本实现呢?您可能想使用一个。为此,请编写一个由页码参数化的方法:
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
...
然后只需使用一个池
,其中包含您认为合适的流程数量(确定此数量可能需要一些实验):
这将设置4个进程,每个进程从Google获取一个页面,然后获取它链接到的每个页面。不直接回答您的问题,而是提出一种途径,使您的代码在单个进程中可用,从而避免不同线程/进程之间的同步问题
为了使所有操作都保持在同一进程中,您最好使用一个支持异步网络操作的框架,如Twisted。在您的代码中,HTML代码的解析可能比获取页面所需的完整网络操作花费的时间要少得多。因此,使用异步IO,您可以同时启动两个请求,并仅在响应到达时解析结果。实际上,每次返回页面时,您的进程都可能在运行循环中处于“空闲”状态。与这个问题正交,但Selenium似乎是一种非常繁重的方法。有什么更好的方法可以做到这一点?(Selenium是我唯一尝试过的与爬行相关的东西)使用HTTP库(请求就是好的)并解析HTML(我会使用BeautifulSoup)。你介意发布符合你所说的扭曲代码吗?Twisted似乎是每个并发问题的解决方案,但很少使用Twisted代码进行备份。我不怀疑Twisted可以做到这一点,但如果你提出这一解决方案,请让我们看看Twisted会带来什么样的代码维护负担。我知道这个包,你能告诉我如何使用该模型来完成上述任务吗?
from multiprocessing import Pool
if __name__ == '__main__':
pool = Pool(processes=4)
pool.map(get_page_data, range(1,101))