Назначьте URL и прокси каждой задаче Python ThreadPoolExecutor
Назначайте прокси до отправки задачи запроса Python, вместо того чтобы позволять рабочим соперничать за общее изменяемое состояние выбора.
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. Избегайте рекурсивных вызовов повторной попытки, которые удаляют записи из общего списка: другой рабочий может выбирать из него, а исчерпанный список всё равно требует явного результата.