Мне нужно сделать множество (тысяч) HTTP-запросов GET на большое количество веб-сайтов. Это довольно медленно, по причинам, по которым некоторые веб-сайты могут не отвечать (или занимать много времени, чтобы сделать это), в то время как другие тайм-аут. Поскольку мне нужно столько ответов, сколько я могу получить, установка небольшого тайм-аута (3-5 секунд) не в мою пользу.Многопроцессорные HTTP-запросы на получение в Python
Мне еще предстоит выполнить многопроцессорную или многопоточную обработку в 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?
Edit:
Я сделал попытку что-то вроде следующего:
# 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__
Что я не» t вполне понимаю. У меня есть небольшая проблема с пониманием , что именно pool.map делает, минуя применение функции на каждом объекте в итерируемом втором параметре. Он что-то возвращает? Если нет, добавьте в глобальную очередь из функции?
Вы прочитали [введение в «многопроцессорную обработку»] (https://docs.python.org/3/library/multiprocessing.html#introduction)? В нем описывается, как это можно сделать. –
@ LutzHorn Да, в частности [https://docs.python.org/3/library/multiprocessing.html#using-a-pool-of-workers] (этот раздел). Я уточнил свой вопрос с более конкретной информацией, относящейся к нему, поскольку, к сожалению, я счел, что документация несколько запутанна. – user991710
Исключение происходит из-за того, что вы используете версию python, которая не поддерживает менеджеров контекста для пула. Поэтому просто не используйте инструкцию with с пулами или переключитесь на самую новую версию. Помимо этого, Pool.map возвращает список со всеми результатами, поэтому с вашим кодом вы создаете очередь списка, содержащую фактический список результатов. В противном случае ваш код кажется прекрасным. – phobic