我必须向许多网站发出无数(数千)个HTTP GET请求。这是相当缓慢的,原因是一些网站可能不响应(或需要很长时间这样做),而其他的时间。由于我需要尽可能多的响应,设置一个小的超时(3-5秒)对我来说不太有利。
我还没有在Python中进行任何类型的多处理或多线程,我已经阅读了很长一段时间的文档。以下是我目前掌握的情况:import requests
from bs4 import BeautifulSoup
from multiprocessing import Process, Pool
errors = 0
def get_site_content(site):
try :
# start = time.time()
response = requests.get(site, allow_redirects = True, timeout=5)
response.raise_for_status()
content = response.text
except Exception as e:
global errors
errors += 1
return ''
soup = BeautifulSoup(content)
for script in soup(["script", "style"]):
script.extract()
text = soup.get_text()
return text
sites = ["http://www.example.net", ...]
pool = Pool(processes=5)
results = pool.map(get_site_content, sites)
print results
现在,我希望返回的结果以某种方式被加入。这允许两种变化:每个进程都有一个本地列表/队列,该列表/队列包含其累积的内容,并将其与其他队列联接以形成单个结果,其中包含所有站点的所有内容。
每个进程在运行时写入单个全局队列。这将需要一些用于并发检查的锁定机制。
在这里,多处理还是多线程是更好的选择?我如何用Python中的任何一种方法来实现上述目标?
编辑:
我确实尝试过如下做法:# global
queue = []
with Pool(processes = 5) as pool:
queue.append(pool.map(get_site_contents, sites))
print queue
但是,这会导致以下错误:with Pool(processes = 4) as pool:
AttributeError: __exit__
我不太明白。通过对iterable second参数中的每个对象应用该函数,我很难理解pool.map究竟做了什么。有没有退货?如果没有,是否从函数中追加到全局队列?