map của một pool truyền cho worker từng mục một. Hãy biến mục đó thành một tác vụ hoàn chỉnh, bao gồm URL và proxy đã chọn, để worker không suy ra tuyến đường của mình từ một danh sách toàn cục đang thay đổi.

Với urls hữu hạn, hãy cung cấp một danh sách URL proxy đã xác thực không rỗng. Các ứng viên HTTP công khai có trong danh sách 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 và handle_result do ứng dụng cung cấp. Bộ điều phối gán các điểm cuối theo thứ tự lặp lại; mỗi worker nhận một cặp cố định. Việc lặp qua các kết quả cũng làm lộ ra ngoại lệ của worker.

Năm worker giới hạn các tác vụ đang hoạt động, không phải tác vụ đang hoạt động trên mỗi proxy. Nếu danh sách có hai điểm cuối, nhiều tác vụ có thể dùng cùng một điểm cuối cùng lúc. Hãy thêm một quy tắc dung lượng riêng cho mỗi điểm cuối khi cần. Để có một tác vụ đang hoạt động cho mỗi URL điểm cuối, một cho thuê hàng đợi đồng bộ có thể giữ chỗ và trả lại từng mục.

Một lần thử lại nên tạo một lần thử có giới hạn mới cho cùng URL. Tránh các lời gọi thử lại đệ quy loại bỏ mục khỏi danh sách dùng chung: một worker khác có thể đang chọn từ đó, và một danh sách đã cạn vẫn cần một kết quả rõ ràng.

Bài viết liên quan