我正在学习如何在Python中使用多个核心。在下面的脚本中,我试图从网页列表中删除标题。
import multiprocessing
import requests
from bs4 import BeautifulSoup
sites = (
'http://penny-arcade.com/',
'http://reallifecomics.com/',
'http://sinfest.net/',
'http://userfriendly.org/',
'http://savagechickens.com/',
'http://xkcd.com/',
'http://duelinganalogs.com/',
'http://cad-comic.com/',
'http://samandfuzzy.com/',
)
def scrape_site(q):
url = q.get()
try:
page = requests.get(url)
soup = BeautifulSoup(page.content, 'lxml')
print url
print soup.title.text
print
except:
print url
print "No TITLE"
print
def run_multicore_scraper():
workers = multiprocessing.cpu_count() # num of cpus or workers
# put all sites into a queue
q = multiprocessing.Queue()
for s in sites:
q.put(s)
# create as many processes as workers
processes = []
for w in xrange(workers):
p = multiprocessing.Process(target=scrape_site, args=(q, ))
p.start()
processes.append(p)
# wait for processes to complete
for p in processes:
p.join()
if __name__ == '__main__':
run_multicore_scraper()
我坚持为什么这个脚本不会遍历所有网站,而是停留在我设置的工作人员数量上。例如,我将工作器数设置为multiprocessing.cpu_count()
计算的CPU数。在我的本地计算机上,即4,我的脚本只迭代到第四个网址。所以,输出看起来像这样:
http://userfriendly.org/
UserFriendly.Org
http://penny-arcade.com/
Penny Arcade
http://sinfest.net/
Sinfest
http://reallifecomics.com/
Real Life Comics ©1999-2016 Greg Dean
由于我的网站列表中有九个网址,因此我预计会有九个打印输出。如果我硬编码2作为我的工作人员数量,脚本将只打印出前2个网址。与6.相同如果我输入一个数字> len(sites)
,所有网址都会打印出来,但系统会挂起,大概是因为有进程已启动但从未完成,因为没有更多的网址可以从队列中处理。
我知道在我的脚本中,我创建了与工作者一样多的进程,但这也是在我创建此玩具示例时所遵循的tutorial中完成的。我认为无论我创建了多少进程,我的脚本都会遍历整个站点列表,就像教程成功完成一样。
有人可以发现为什么我的脚本不会遍历我的整个网站列表而是在第n个元素处停下来,而n =#workers?
答案 0 :(得分:2)
您的scrape_site
方法只搜索一个网站 - 它不会循环尝试从队列中提取越来越多的事件。你在这里派遣了4名工人:
for w in xrange(workers):
p = multiprocessing.Process(target=scrape_site, args=(q, ))
p.start()
processes.append(p)
所以每个4工作人员都会启动,运行你告诉他们运行的方法,这会刮掉一个网站,然后他们就完成了。
一种方法是让scrape_site
方法运行一个循环从队列中拉出站点,直到它们发现队列为空。另一种选择是使用该库中的worker pool内容而只是把那些网站清单拿去。