Соскреб, посылая параллельные запросы с Python
У меня есть Python 3.4, и я установил запросы и несколько других необходимых программ для очистки веб-страниц. Моя проблема в том, что я хотел бы очистить около 7000 страниц (только html/text), и не хочу делать все это сразу, я хотел бы иметь некоторую задержку, чтобы я не попал на серверы слишком много запросов и потенциально могут быть забанены. Я слышал о греках, но, видимо, у них нет его для python 3.4 (реальная ошибка говорит, что он не может найти vcvarsall.bat, но в документации я не видел никакой поддержки для 3.4). Кто-нибудь знает альтернативную программу, которая может управлять запросами URL? Другими словами, я не стремлюсь схватить все как можно быстрее, а скорее медленно и устойчиво.
1 ответ
Я предлагаю развернуть вашу собственную многопоточную программу для выполнения запросов. я нашел concurrent.futures
быть самым простым способом многопоточности таких запросов, в частности, используя ThreadPoolExecutor
, У них даже есть простой многопоточный пример запроса URL в документации.
Что касается второй части вопроса, это действительно зависит от того, насколько / насколько вы хотите ограничить свои запросы. Для меня настройка достаточно низкая max_workers
аргумент и, возможно, в том числе time.sleep
ожидания в моей функции было достаточно, чтобы избежать каких-либо проблем, даже при очистке десятков тысяч страниц, но это, очевидно, во многом зависит от сайта, который вы пытаетесь очистить. Это не должно быть трудно осуществить какое-то пакетирование или ожидание, хотя.
Следующий код не проверен, но мы надеемся, что это может быть отправной точкой. Отсюда, вы, вероятно, хотите изменить get_url_data
(или любую функцию, которую вы используете) с тем, что вам нужно сделать (например, анализ, сохранение).
import concurrent.futures as futures
import requests
from requests.exceptions import HTTPError
urllist = ...
def get_url_data(url, session):
try:
r = session.get(url, timeout=10)
r.raise_for_status()
except HTTPError:
return None
return r.text
s = requests.Session()
try:
with futures.ThreadPoolExecutor(max_workers=5) as ex:
future_to_url = {ex.submit(get_url_data, url, s): url
for url in urlist}
results = {future_to_url[future]: future.result()
for future in futures.as_completed(future_to_url)}
finally:
s.close()