这是我的程序布局:
一些进程专门用于从长长的URL列表中获取,BeautifulSouping和编码(因为BeautifulSoup对象无法被腌制)。此HTML为put()
multiprocessing.JoinableQueue()
。还有一些,从队列中单独处理get()
,重新BeautifulSoup并解析HTML,并用一些数据填充本地字典。然后将字典传递到另一个队列 - 专用线程将它们作为行写入文件。
我正在创建这样的流程:
numProcesses = 6
numGetProcesses = 3
# Get HTML
getProcesses = []
for ii in range(numGetProcesses):
newProcess = GetHTML(urlInputQ, htmlOutputQ)
getProcesses.append(newProcess)
newProcess.start()
# Parse HTML
parseProcesses = []
for ii in range(numProcesses - numGetProcesses)
newProcess = ParseHTML(htmlOutputQ, dataOutputQ)
parseProcesses.append(newProcess)
newProcess.start()
然后,如果GetHTML
进程在ParseHTML
进程之前完成了他们的工作,我[认为我]终止它们,并创建新的ParseHTML
进程:
for process in getProcesses: process.join() # Wait for HTML
# Dedicate newly freed CPU to parsing
print('Redistributing wealth...')
for ii in range(numGetProcesses):
oldProcess = getProcesses.pop()
oldProcess.terminate()
newProcess = csdb.ParseHTML(htmlOutputQ, dataOutputQ)
parseProcesses.append(newProcess)
newProcess.start()
我希望首先将3个进程用于获取HTML和3个进程来解析HTML。然后,当HTML-getting完成时,应该有6个进程解析HTML。出现了两个问题,我认为可能导致这些问题的是对我的结局的误解:
1)当我将numGetProcesses
更改为1或5时,我发现总体程序速度没有差异(大约有1000个网址,大约3分钟就完成了)。
2)我也发现HTML-get和HTML-parse队列清空所需的时间没有区别
3)消息"重新分配财富......" 总是在ParseHTML
进程完全清空其队列之前弹出几秒钟。也就是说,GetHTML
进程(无论是1还是5)同时完成,同时相对于ParseHTML
进程完成。
在我看来,无论我设置了什么数字或启动了多少进程,都会运行每个函数的固定数量的进程。有没有人有任何想法?
抱歉,我无法提供完整的工作代码。它太大了。但是,这里是GetHTML
类的样子。 ParseHTML
类的设置类似,但 lot 更多:
class GetHTML(multiprocessing.Process):
def __init__(self, inputQ, outputQ):
multiprocessing.Process.__init__(self)
self.inputQ = inputQ
self.outputQ = outputQ
self.data = df_base.copy()
def run(self):
while True:
for key in self.data.keys(): self.data[key] = None
info = self.inputQ.get()
if info == "die": break
self.data['id'] = info[1]
self.data['date'] = info[2]
uncookedHTML = CookSoup(info[0])
encodedHTML = uncookedHTML.encode('utf-8')
self.outputQ.put([self.data, encodedHTML])
self.inputQ.task_done()
CookSoup(URL):
ua = 'Mozilla/5.0 (X11; Linux x86_64; rv:18.0) Gecko/20100101 Firefox/18.0 (compatible;)' #For User-Agent header
def CookSoup(url):
request = urllib2.Request(url) # Requests URL
request.add_header('User-Agent', ua) # Adds User Agent
response = urllib2.urlopen(request) # Opens URL
soup = BeautifulSoup(response) # Creates soup
response.close() #Closes file
return soup #Returns the HTML