Соскреб, посылая параллельные запросы с 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() 
Другие вопросы по тегам