map puli przekazuje pracownikowi po jednym elemencie. Uczyń ten element pełnym zadaniem, obejmującym URL i wybrane proxy, aby pracownik nie wnioskował swojej trasy ze zmieniającej się listy globalnej.

Dla skończonej liczby urls podaj niepustą listę zweryfikowanych URL proxy. Publiczni kandydaci HTTP są dostępni na liście proxy 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 i handle_result dostarcza aplikacja. Koordynator przydziela punkty końcowe w powtarzającej się kolejności; każdy pracownik otrzymuje jedną stałą parę. Iterowanie wyników ujawnia także wyjątki pracowników.

Pięciu pracowników ogranicza aktywne zadania, a nie aktywne zadania na proxy. Jeśli lista ma dwa punkty końcowe, kilka zadań może jednocześnie używać tego samego punktu końcowego. W razie potrzeby dodaj osobną regułę pojemności dla każdego punktu końcowego. Dla jednego aktywnego zadania na URL punktu końcowego synchronizowany leasing kolejki może zarezerwować i zwrócić każdy wpis.

Ponowna próba powinna utworzyć nową ograniczoną próbę dla tego samego URL. Unikaj rekurencyjnych wywołań ponownej próby, które usuwają wpisy ze współdzielonej listy: inny pracownik może z niej wybierać, a wyczerpana lista nadal wymaga jednoznacznego wyniku.

Powiązane artykuły