map пулу передає робітнику по одному елементу за раз. Зробіть цей елемент повною задачею, включно з URL і вибраним проксі, щоб робітник не виводив свій маршрут зі змінюваного глобального списку.

Для скінченної кількості urls надайте непорожній список перевірених URL проксі. Публічні кандидати HTTP доступні в списку HTTP-проксі:

from concurrent.futures import ThreadPoolExecutor
from itertools import cycle
import requests

def fetch(job):
    url, proxy_url = job
    proxies = {"http": proxy_url, "https": proxy_url}
    with requests.get(url, proxies=proxies, timeout=(5, 15)) as response:
        response.raise_for_status()
        return url, response.text

if not proxy_urls:
    raise ValueError("No proxy endpoints were supplied")

jobs = zip(urls, cycle(proxy_urls))
with ThreadPoolExecutor(max_workers=5) as executor:
    for url, body in executor.map(fetch, jobs):
        handle_result(url, body)

urls, proxy_urls і handle_result надає застосунок. Координатор призначає кінцеві точки в повторюваному порядку; кожен робітник отримує одну фіксовану пару. Перебір результатів також виявляє винятки робітників.

П'ять робітників обмежують активні задачі, а не активні задачі на проксі. Якщо у списку дві кінцеві точки, кілька задач можуть одночасно використовувати ту саму кінцеву точку. За потреби додайте окреме правило місткості для кожної кінцевої точки. Для однієї активної задачі на URL кінцевої точки синхронізована оренда черги може резервувати й повертати кожен запис.

Повторна спроба має створювати нову обмежену спробу для того самого URL. Уникайте рекурсивних викликів повторної спроби, які видаляють записи зі спільного списку: інший робітник може вибирати з нього, а вичерпаний список усе ще потребує явного результату.

Схожі статті