풀의 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에 대해 새롭게 제한된 시도를 만들어야 합니다. 공유 목록에서 항목을 제거하는 재귀적 재시도 호출은 피하세요. 다른 작업자가 그 목록에서 선택 중일 수 있고, 소진된 목록에도 여전히 명시적인 결과가 필요합니다.

관련 글