map unui pool transmite lucrătorului câte un element. Fă din acel element o sarcină completă, incluzând URL-ul și proxy-ul selectat, astfel încât lucrătorul să nu-și deducă ruta dintr-o listă globală schimbătoare.

Pentru urls finite, furnizează o listă nevidă de URL-uri de proxy validate. Candidați HTTP publici sunt disponibili în lista de 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 sunt furnizate de aplicație. Coordonatorul atribuie punctele finale într-o ordine repetitivă; fiecare lucrător primește o pereche fixă. Iterarea rezultatelor expune și excepțiile lucrătorilor.

Cinci lucrători limitează sarcinile active, nu sarcinile active per proxy. Dacă lista are două puncte finale, mai multe sarcini pot folosi același punct final simultan. Adaugă o regulă separată de capacitate per punct final atunci când este necesar. Pentru o sarcină activă per URL de punct final, un închiriere de coadă sincronizată poate rezerva și returna fiecare intrare.

O nouă încercare ar trebui să creeze o încercare limitată nouă pentru același URL. Evită apelurile recursive de reîncercare care elimină intrări dintr-o listă partajată: un alt lucrător s-ar putea să selecteze din ea, iar o listă epuizată are încă nevoie de un rezultat explicit.

Articole similare