Aiohttp работа с proxy

Aiohttp поддерживает работу с HTTP и HTTPS, но с SOCKS дела обстоят немного сложнее. В этом этапе мы рассмотрим работу со всеми видами прокси.

Код ниже продемонстрирует простое использование HTTP-прокси с применением basic authentication, которое используется на большинстве сайтов.

import aiohttp
import asyncio

url = 'http://httpbin.org/ip'
async def main():
    proxy = 'http://127.0.0.1:80'
    async with aiohttp.ClientSession(trust_env=True) as session:
        proxy_auth = aiohttp.BasicAuth('user', 'pass')
        async with session.get(url=url, proxy=proxy, proxy_auth=proxy_auth) as response:
            print(await response.text())
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(main())

В коде выше добавилась одна новая строка: proxy_auth = aiohttp.BasicAuth(‘user’, ‘pass’), которая управляет авторизацией к прокси-серверу. Также обратите внимание, что мы передаём прокси в формате http://127.0.0.1:80, аналогично тому, как мы делали это в библиотеке requests.

Если ваши прокси не требуют авторизации по логину и паролю, достаточно убрать переменную proxy_auth.

Код ниже выполнит запрос через прокси. Если у вас есть рабочий прокси, можете запустить этот код с ним. Если рабочего прокси у вас нет, качественные прокси можно купить тут.

import aiohttp
import asyncio

url = 'http://httpbin.org/ip'
async def main():
    proxy = 'http://127.0.0.1:80'
    async with aiohttp.ClientSession() as session:
        async with session.get(url=url, proxy=proxy) as response:
            print(await response.text())
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(main())

Для запуска следующего кода нам понадобится файл с прокси.

import time
import aiohttp
import asyncio
import aiofiles

url = 'http://httpbin.org/ip'

async def check_proxy(prx, semaphore):
    proxy = f'http://{prx}'
    async with semaphore:
        try:
            async with aiohttp.ClientSession() as session:
                async with session.get(url=url, proxy=proxy, timeout=1) as response:
                    if response.ok:
                        return f'good proxy, status_code: {response.status}, {prx}'
                    else:
                        return f'bad proxy, status_code: {response.status}, {prx}'
        except Exception as e:
            return f'bad proxy, Error: {e.__class__.__name__}, {prx}'
async def main():
    # Внимание! Этот оператор ограничивает количество одновременно выполняемых задач
    # Если код падает с ошибкой ValueError: too many file descriptors in select(),
    # уменьшите это число
    semaphore = asyncio.BoundedSemaphore(500)
    async with aiofiles.open('proxy.txt', mode='r', encoding='utf8') as f:
        # Получаем список прокси из файла
        proxies = await f.readlines()
        # Создаем и асинхронно запускаем список задач на проверку прокси
        tasks = [check_proxy(prx.strip(), semaphore) for prx in proxies]
        # Ждем, пока выполнятся все проверки
        result = await asyncio.gather(*tasks, return_exceptions=True)
        # Выводим результат проверки
        print(f"Всего проверено: {len(result)} шт.")
        print(*result, sep='\n')
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
start = time.time()
asyncio.run(main())
print(f'Затрачено времени: {time.time() - start} секунд')

Вывод:

Всего проверено: 3812 шт.
bad proxy, Error: TimeoutError, 93.184.4.254:1080
bad proxy, Error: TimeoutError, 162.243.140.82:38908
bad proxy, Error: ServerDisconnectedError, 50.197.210.138:32100
..........
bad proxy, Error: TimeoutError, 185.177.158.174:3128
good proxy, status_code: 200, 20.206.106.192:80
good proxy, status_code: 200, 123.205.68.113:8193
bad proxy, Error: TimeoutError, 167.71.41.76:8080
..........
bad proxy, status_code: 409, 172.67.31.153:80
bad proxy, Error: TimeoutError, 212.83.138.245:29847
bad proxy, Error: TimeoutError, 95.216.164.24:8080
bad proxy, Error: TimeoutError, 188.166.64.160:3128
bad proxy, Error: TimeoutError, 212.83.138.245:54433
bad proxy, Error: TimeoutError, 185.73.115.199:7778
bad proxy, Error: TimeoutError, 63.141.128.108:80
bad proxy, Error: TimeoutError, 212.51.144.107:80
Затрачено времени: 6.812376976013184 секунд

Про aiofiles мы будем говорить в следующем разделе курса.

Если коротко, то этот код пингует сайт http://httpbin.org/ip через предоставленные нами прокси и делает это в асинхронном стиле. Такой код будет работать быстрее синхронного. В этом коде установлен timeout=1, а это значит, что синхронный код ждал бы одну секунду, после чего возвращал бы ответ. Если в нашем списке имеется ~3800 шт прокси, итого, мы потратим 3800 / 60 = ~63 минуты на проверку всех прокси. На моей машине проверка всех прокси в асинхронном стиле заняла почти 7 секунд. Разницу оцените сами: 3812 vs 7!!!

Ключевая разница двух подходов в том, что синхронный код бездействует, пока ждет ответа от сервера, а асинхронный код во время ожидания ответа отправляет новый запрос, при таком подходе время бездействия крайне мало.

 В коде выше мы придаём прокси вид.

http://203.30.190.95:80
http://185.162.231.55:80
http://203.30.190.152:80
http://203.28.9.1:80

Если мы хотим использовать прокси с авторизацией по логину и паролю, то вид у прокси должен быть следующий.

http://login:password@203.28.8.151:80
http://login:password@162.247.243.185:80
http://login:password@172.67.186.212:80
http://login:password@50.204.190.234:80

или использовать  BasicAuth, (документация — https://docs.aiohttp.org/en/stable/client_advanced.html#proxy-support).

proxy = 'http://23.227.38.102:80'
proxy_auth = aiohttp.BasicAuth('your_user', 'your_password')

async with session.get(url, proxy=proxy, proxy_auth=proxy_auth) as response:
    # Получаем содержимое ответа в виде текста
    html = await response.text()
    # Передаем содержимое в BeautifulSoup
    return BeautifulSoup(html, 'html.parser')


Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: