Работаем с Proxy в Python

 

Что такое Proxy?

В самом простом определении, прокси-сервер (Proxy Server) – это посредник между вашим компьютером (клиентом) и сервером, к которому вы хотите обратиться.

Представьте себе курьера, который берет ваш запрос, относит его в нужное место, забирает ответ и возвращает его вам. При этом получатель (сервер) видит не вас, а курьера.

Визуальная схема работы прокси:

Чтобы лучше понять, как это работает, давайте посмотрим на схему:

Клиент (Ваш компьютер) --> Прокси-сервер --> Сервер (Веб-сайт, API) --> Прокси-сервер --> Клиент
  • Клиент: Это ваш компьютер, смартфон, или любое другое устройство, отправляющее запрос в интернет.
  • Прокси-сервер: Это сервер, который принимает ваш запрос, перенаправляет его на целевой сервер и возвращает вам ответ.
  • Сервер: Это сервер, на котором находится ресурс, к которому вы обращаетесь (например, веб-сайт, API).

Таким образом, когда вы используете прокси, сервер видит IP-адрес и другие данные прокси-сервера, а не ваши собственные.

Зачем нужны Proxy?

Теперь, когда мы понимаем, что такое прокси, давайте разберемся, зачем их используют. Причины могут быть разными, и выбор прокси зависит от конкретной задачи.

  • Анонимность и сокрытие IP-адреса: Это, пожалуй, самая распространенная причина использования прокси. Скрывая ваш реальный IP-адрес, прокси позволяет вам оставаться анонимным в сети. Это может быть полезно для защиты вашей конфиденциальности, особенно если вы не хотите, чтобы ваши действия в интернете были отслежены.
  • Обход географических ограничений: Многие сервисы и веб-сайты ограничивают доступ в зависимости от вашего географического местоположения (например, видеоконтент, доступный только в определенных странах). Используя прокси, расположенный в нужной стране, вы можете обойти эти ограничения и получить доступ к заблокированному контенту.
  • Балансировка нагрузки: Крупные веб-сайты и сервисы часто используют прокси для распределения нагрузки между несколькими серверами. Это позволяет повысить производительность и отказоустойчивость.
  • Кеширование контента: Прокси могут кешировать часто запрашиваемый контент (например, изображения, CSS, JavaScript). Это позволяет ускорить загрузку веб-страниц для пользователей, поскольку прокси отдает контент из кеша, а не запрашивает его с удаленного сервера.
  • Тестирование и разработка: Разработчики могут использовать прокси для тестирования веб-приложений в различных сетевых условиях или для имитации пользователей из разных стран.
  • Web Scraping и обход блокировок: Web Scraping – это процесс автоматического извлечения данных с веб-сайтов. Сайты часто блокируют запросы от скриптов, чтобы предотвратить злоупотребления. Использование прокси позволяет обходить эти блокировки, отправляя запросы с разных IP-адресов. Это очень важная тема, которую мы рассмотрим подробнее позже.

Правовые и этические аспекты использования прокси

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

  • Уважение условий использования сайтов и API: Прежде чем использовать прокси для доступа к какому-либо веб-сайту или API, внимательно прочитайте их условия использования. Многие сервисы запрещают автоматический доступ к их контенту, и обход этих правил может привести к блокировке вашего аккаунта или даже к юридическим последствиям.
  • Избежание злоупотреблений (спам, DDoS и т.д.): Категорически запрещено использовать прокси для рассылки спама, организации DDoS-атак или других видов злонамеренной деятельности. Эти действия являются незаконными и могут нанести серьезный ущерб.
  • Законность использования прокси в разных юрисдикциях: В некоторых странах использование прокси может быть ограничено или даже запрещено. Перед использованием прокси убедитесь, что это разрешено законодательством вашей страны.

Всегда используйте прокси ответственно и этично. Не нарушайте правила веб-сайтов и API. Не используйте прокси для незаконной деятельности.

 

Использование Proxy в Python

Мы будем использовать библиотеку requests, которая является стандартом для отправки HTTP-запросов в Python.

requests – элегантная и мощная библиотека Python, упрощающая отправку HTTP-запросов. Она предоставляет удобный API для работы с различными типами запросов (GET, POST, PUT, DELETE и т.д.) и ответов.

Установка библиотеки:

  • pip install requests

Основные методы:

  • requests.get(url, params=None, **kwargs): Отправка GET-запроса.

  • requests.post(url, data=None, json=None, **kwargs): Отправка POST-запроса.

  • requests.put(url, data=None, **kwargs): Отправка PUT-запроса.

  • requests.delete(url, **kwargs): Отправка DELETE-запроса.

  • requests.head(url, **kwargs): Отправка HEAD-запроса (получение только заголовков).

  • requests.options(url, **kwargs): Отправка OPTIONS-запроса.

Параметры запроса:

  • url: URL-адрес, к которому отправляется запрос.

  • params: Словарь или байты, которые будут отправлены в строке запроса GET.

  • data: Словарь, список кортежей (key=value), байты или file-like object для отправки в теле POST-запроса (обычно для application/x-www-form-urlencodedданных).

  • json: JSON-сериализованные данные для отправки в теле POST-запроса (application/json).

  • headers: Словарь с HTTP-заголовками.

  • cookies: Словарь с cookie.

  • auth: Кортеж (username, password) для базовой аутентификации.

  • timeout: Время ожидания ответа в секундах. Критически важно указывать!

  • proxies: Словарь с настройками прокси (то, что мы будем использовать).

  • verify: Boolean. Проверка SSL-сертификата (по умолчанию True). Можно установить в False, если есть проблемы с сертификатами, но это снижает безопасность.

  • stream: Boolean. Если True, то тело ответа не будет скачано сразу, а будет доступно для потоковой обработки.

  • cert: Путь к файлу сертификата или кортеж с путями к сертификату и приватному ключу для TLS-клиентской аутентификации.

Объект ответа (Response):

  • response.status_code: Код HTTP-ответа (например, 200 OK, 404 Not Found).

  • response.text: Текст ответа (обычно HTML).

  • response.content: Байтовое представление ответа.

  • response.json(): Преобразование JSON-ответа в словарь Python.

  • response.headers: Словарь с HTTP-заголовками ответа.

  • response.cookies: Объект RequestsCookieJar с cookie.

  • response.url: URL-адрес, к которому был отправлен запрос (может отличаться от исходного URL в случае редиректов).

  • response.raise_for_status(): Метод, который вызывает исключение HTTPError, если код ответа не является успешным (между 200 и 400). Рекомендуется всегда вызывать этот метод после получения ответа, чтобы убедиться, что запрос был выполнен успешно.

 

Использование Proxy с requests в Python

Основной способ использования прокси с requests - это передача параметров proxies в методы requests.get(), requests.post(), requests.put(), requests.delete() и другие методы для отправки HTTP-запросов.

  • import requests
    
    proxies = {
        'http': 'http://192.168.1.100:8080',
        'https': 'http://192.168.1.100:8080', # Можно использовать тот же прокси для HTTPS
    }
    
    try:
        response = requests.get('http://example.com', proxies=proxies, timeout=10)
        response.raise_for_status()
        print(f"Статус код: {response.status_code}")
        print(f"Содержимое:\n{response.text[:200]}...") # Вывод первых 200 символов
    except requests.exceptions.RequestException as e:
        print(f"Ошибка при запросе: {e}")

Параметр proxies принимает словарь, где ключи - это протоколы (http, https), а значения - URL прокси-сервера.

proxies = {
  'http': 'http://user:pass@ip:port',
  'https': 'https://user:pass@ip:port',
}
  • http: Прокси-сервер для HTTP-запросов.
  • https: Прокси-сервер для HTTPS-запросов.
  • user:pass: (Опционально) Логин и пароль для аутентификации на прокси-сервере.
  • ip:port: IP-адрес и порт прокси-сервера.

Обратите внимание на параметр timeout. Он задает максимальное время ожидания ответа от сервера. Если ответ не получен в течение этого времени, requests вызовет исключение requests.exceptions.Timeout. Это полезно, чтобы предотвратить зависание программы, если прокси-сервер не отвечает. Рекомендуется всегда указывать таймаут.

 

Использование SOCKS прокси в Python

  • import requests
    
    proxies = {
        'http': 'socks5://user:password@127.0.0.1:1080',  # Замените на ваши данные
        'https': 'socks5://user:password@127.0.0.1:1080',
    }
    
    try:
        response = requests.get('https://www.google.com', proxies=proxies, timeout=10)
        response.raise_for_status()
        print(f"Статус код: {response.status_code}")
        print(f"Содержимое:\n{response.text[:200]}...")  # Вывод первых 200 символов
    except requests.exceptions.RequestException as e:
        print(f"Ошибка при запросе: {e}")
    except ImportError as e:
        print("Для использования SOCKS прокси установите requests[socks]: pip install requests[socks]")

Для использования SOCKS прокси с requests необходимо установить дополнительные зависимости:

  • pip install requests[socks]

Эта команда установит библиотеки PySocks или SocksiPy, которые необходимы для поддержки SOCKS протоколов. Без этого requests не сможет обработать SOCKS прокси.

 

Аутентификация Proxy в Python (с HTTPProxyAuth)

Некоторые прокси-серверы требуют аутентификации (логин и пароль). requestsпредоставляет класс HTTPProxyAuth для передачи учетных данных.

  • import requests
    from requests.auth import HTTPProxyAuth
    
    proxies = {
        'http': 'http://192.168.1.100:8080',
        'https': 'http://192.168.1.100:8080',
    }
    auth = HTTPProxyAuth('myuser', 'mypassword')
    
    try:
        response = requests.get('http://example.com', proxies=proxies, auth=auth, timeout=10)
        response.raise_for_status()
        print(f"Статус код: {response.status_code}")
        print(f"Содержимое:\n{response.text[:200]}...")
    except requests.exceptions.RequestException as e:
        print(f"Ошибка при запросе: {e}")

Если у вас есть логин и пароль для прокси, обязательно используйте HTTPProxyAuth. Не передавайте логин и пароль прямо в URL прокси (например, 'http://user:pass@ip:port'), так как это небезопасно и может быть несовместимо с некоторыми прокси-серверами.

 

Проверка своего IP-адреса через Proxy в Python

Одним из способов убедиться, что прокси работает, является отправка запроса на сайт, который показывает ваш IP-адрес.

  • import requests
    
    proxies = {
        'http': 'http://192.168.1.100:8080',
        'https': 'http://192.168.1.100:8080',
    }
    
    try:
        response = requests.get('https://api.ipify.org?format=json', proxies=proxies, timeout=10) # Популярный сервис для получения IP
        response.raise_for_status()
        ip_data = response.json()
        print(f"Ваш IP-адрес через прокси: {ip_data['ip']}")
    
    except requests.exceptions.RequestException as e:
        print(f"Ошибка при запросе: {e}")

     

Этот пример будет очень общим, так как для реальной работы с YouTube API требуется ключ и знания самого API. Идея - найти прокси из нужной страны и использовать его.

  • # Псевдокод (требует реальный YouTube API key и выбор прокси из нужной страны)
    # Подключаемся к API прокси
    # выбираем страну
    import requests
    import json
    
    proxy_api_url = "https://proxyprovider.com/api/getproxy?country=US" # заменить url на реальный сервис
    
    try:
        response = requests.get(proxy_api_url)
        response.raise_for_status()
        proxy_data = response.json() # json
        print(proxy_data['proxy'])
        proxies = {
        'http': proxy_data['proxy'],
        'https': proxy_data['proxy'],
        }
        auth = HTTPProxyAuth('myuser', 'mypassword')
        response = requests.get('http://youtube.com', proxies=proxies, auth=auth, timeout=10)
        print (f"Получилось {response.status_code}")
    
    except requests.exceptions.RequestException as e:
        print(f"Ошибка при запросе: {e}")

Этот пример показывает только общий подход. Для реальной работы потребуется изучить YouTube API и найти надежный источник прокси, расположенных в нужных странах.

 

Обработка ошибок для работы с Proxy в Python

При работе с прокси могут возникать различные ошибки, например, прокси-сервер недоступен, неправильный логин/пароль, или таймаут соединения. Важно обрабатывать эти ошибки, чтобы программа не завершалась аварийно.

Можно обрабатывать разные типы исключений более детально, чтобы предпринять разные действия в зависимости от типа ошибки.

  • import requests
    from requests.exceptions import Timeout, ConnectionError, ProxyError, HTTPError
    
    proxies = {
        'http': 'http://invalid_proxy:8080',
        'https': 'http://invalid_proxy:8080',
    }
    
    try:
        response = requests.get('http://example.com', proxies=proxies, timeout=5)
        response.raise_for_status() # Проверяем код ответа
        print(response.status_code)
        print(response.text)
    except Timeout:
        print("Превышено время ожидания ответа от сервера.")
    except ConnectionError:
        print("Не удалось установить соединение с прокси-сервером.")
    except ProxyError:
        print("Произошла ошибка на прокси-сервере.")
    except HTTPError as e:
        print(f"HTTP ошибка: {e.response.status_code}")
    except requests.exceptions.RequestException as e:
        print(f"Произошла общая ошибка: {e}") # Общая ошибка, которая ловит все остальные

 

Иногда (очень редко и не рекомендуется) может потребоваться отключить проверку SSL-сертификатов, если есть проблемы с сертификатом прокси-сервера.

  • response = requests.get('https://example.com', proxies=proxies, verify=False, timeout=10)

Отключение проверки сертификатов снижает безопасность вашего соединения. Используйте это только в крайнем случае и только если вы полностью доверяете прокси-серверу. Лучше сначала попробовать решить проблему с сертификатом.

В случае временных сетевых проблем можно реализовать логику повторных попыток. Для этого можно использовать библиотеку requests-retry. Или можно написать свою логику с циклами и time.sleep().

 

Продвинутые техники работы с Proxy в Python

Выше в лекции мы изучили основы работы с прокси в Python, используя библиотеку requests. Мы узнали, как подключаться к прокси, как обрабатывать аутентификацию и как справляться с основными ошибками. Теперь пришло время перейти на следующий уровень и рассмотреть продвинутые техники, которые помогут вам эффективно использовать прокси для web scraping, обхода географических ограничений и других задач, требующих высокой надежности и анонимности.

Список Proxy и Ротация Proxy в Python

Одной из основных проблем при использовании прокси является их нестабильность. Прокси могут быть медленными, ненадежными или заблокированы целевыми сайтами. Чтобы решить эту проблему, применяется техника ротации прокси – использование списка доступных прокси и случайный выбор одного из них для каждого запроса.

Сначала вам необходимо собрать список прокси. Можно получить их из различных источников:

  • Бесплатные прокси: Будьте осторожны с бесплатными прокси, так как они часто медленные, ненадежные и могут содержать вредоносный код. Их можно найти на различных веб-сайтах, но будьте готовы к тому, что большая часть из них будет нерабочей.

  • Платные прокси: Платные прокси-сервисы предоставляют более надежные и быстрые прокси, часто с гарантированной анонимностью и поддержкой различных протоколов (HTTP, SOCKS).

  • Собственный прокси-сервер: Если у вас есть возможность, вы можете настроить собственный прокси-сервер на VPS или выделенном сервере.

Пример списка прокси:

proxies = [
    {'http': 'http://user1:pass1@192.168.1.100:8080', 'https': 'http://user1:pass1@192.168.1.100:8080'},
    {'http': 'http://user2:pass2@192.168.1.101:8080', 'https': 'http://user2:pass2@192.168.1.101:8080'},
    {'http': 'socks5://user3:pass3@127.0.0.1:1080', 'https': 'socks5://user3:pass3@127.0.0.1:1080'},
]

Используйте модуль random для случайного выбора прокси из списка:

import random
import requests

def get_random_proxy(proxies):
    return random.choice(proxies)

def make_request(url, proxies):
    proxy = get_random_proxy(proxies)
    try:
        response = requests.get(url, proxies=proxy, timeout=10)
        response.raise_for_status()
        print(f"Успешно скачано с использованием прокси: {proxy}")
        return response
    except requests.exceptions.RequestException as e:
        print(f"Ошибка при запросе с прокси {proxy}: {e}")
        return None

# Пример использования:
if __name__ == '__main__':
    url = "http://example.com"
    response = make_request(url, proxies)
    if response:
        print(response.status_code)

Не все прокси в вашем списке могут быть рабочими. Важно периодически проверять их работоспособность и удалять неработающие из списка. Для проверки можно отправлять запрос на специальный сайт, который возвращает ваш IP-адрес (например, https://api.ipify.org?format=json). Если IP, возвращенный сайтом, совпадает с IP прокси-сервера, значит, прокси работает.

import requests
import random

def is_proxy_working(proxy):
    try:
        response = requests.get("https://api.ipify.org?format=json", proxies=proxy, timeout=5)
        response.raise_for_status()
        ip_data = response.json()
        print(f"IP адрес с прокси {proxy}: {ip_data['ip']}")
        return True
    except requests.exceptions.RequestException:
        return False

def filter_working_proxies(proxies):
    working_proxies = []
    for proxy in proxies:
        if is_proxy_working(proxy):
            working_proxies.append(proxy)
        else:
            print(f"Прокси {proxy} не работает и будет удален.")
    return working_proxies

# Пример использования:
if __name__ == '__main__':
    proxies = [
        {'http': 'http://45.155.205.200:8000', 'https': 'http://45.155.205.200:8000'}, # Пример рабочего прокси (на момент написания статьи)
        {'http': 'http://invalid_proxy:8080', 'https': 'http://invalid_proxy:8080'}, # Пример нерабочего прокси
    ]
    working_proxies = filter_working_proxies(proxies)
    print(f"Рабочие прокси: {working_proxies}")

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

 

Proxy Broker: Автоматический поиск и проверка прокси в Python

Proxy Broker – это удобная библиотека Python, которая позволяет автоматически искать и проверять прокси. Она поддерживает различные протоколы (HTTP, SOCKS4, SOCKS5) и предоставляет фильтры для поиска прокси с определенными характеристиками (анонимность, страна, скорость и т.д.).

pip install proxybroker

Пример поиска анонимных и элитных прокси:

import asyncio
from proxybroker import Broker

async def show_proxies(limit=10):
    broker = Broker()
    proxies = asyncio.Queue()
    broker.find(proxies, limit=limit, countries=['US', 'CA'],  # Ищем прокси из США и Канады
               anonymity_level=2)  # Анонимные или элитные прокси
    num = 0
    while True:
        proxy = await proxies.get()
        if proxy is None:
            break
        num += 1
        print(f'{num}: {proxy}')

async def main():
    await show_proxies()

if __name__ == '__main__':
    asyncio.run(main())

Этот код использует asyncio (асинхронное программирование) для поиска прокси. Вам потребуется запустить его в асинхронном контексте.

  • broker.find() ищет прокси и помещает их в очередь proxies.

  • limit ограничивает количество найденных прокси.

  • countries фильтрует прокси по стране.

  • anonymity_level:

    • 1: Прозрачные прокси.

    • 2: Анонимные прокси.

    • 3: Элитные прокси.

Интеграция proxybroker с requests:

Чтобы использовать найденные прокси с requests, нужно получить их в нужном формате и передать в параметр proxies:

import asyncio
from proxybroker import Broker
import requests

async def get_proxies(limit=10):
    broker = Broker()
    proxies_queue = asyncio.Queue()
    await broker.find(proxies_queue, limit=limit, countries=['US'], anonymity_level=2)
    proxies = []
    while not proxies_queue.empty():
        proxy = await proxies_queue.get()
        if proxy:
            if proxy.is_ssl:
                proxies.append({'https': f'http://{proxy.host}:{proxy.port}'})
            else:
                proxies.append({'http': f'http://{proxy.host}:{proxy.port}'})
    return proxies

async def main():
    proxies = await get_proxies()
    if proxies:
        print("Найденные прокси:")
        for proxy in proxies:
            print(proxy)
        try:
            proxy = random.choice(proxies) # Берем случайный прокси
            response = requests.get('https://api.ipify.org?format=json', proxies=proxy, timeout=10) # Проверяем через ipify
            response.raise_for_status()
            ip_data = response.json()
            print(f"IP адрес с прокси {proxy}: {ip_data['ip']}")

        except requests.exceptions.RequestException as e:
             print(f"Ошибка при запросе с прокси {proxy}: {e}")

if __name__ == '__main__':
    asyncio.run(main())

Альтернативные библиотеки: aiohttp для асинхронных запросов

Для высокопроизводительного парсинга и других задач, требующих большого количества параллельных запросов, можно использовать асинхронную библиотеку aiohttp. aiohttp позволяет отправлять запросы неблокирующим образом, что значительно повышает эффективность.

import aiohttp
import asyncio

async def fetch(session, url, proxy):
    try:
        async with session.get(url, proxy=f"http://{proxy}", timeout=10) as response:
            response.raise_for_status()
            return await response.text()
    except aiohttp.ClientError as e:
        print(f"Ошибка при запросе {url} через прокси {proxy}: {e}")
        return None

async def main():
    proxy = "http://user:pass@192.168.1.100:8080" # Пример прокси
    url = "http://example.com"

    async with aiohttp.ClientSession() as session:
        html = await fetch(session, url, proxy)
        if html:
            print(f"Успешно скачано:\n{html[:200]}...")

if __name__ == "__main__":
    asyncio.run(main())

 

Обход сложных защит от ботов

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

  • User-Agent Rotation: Использование разных User-Agent для имитации разных браузеров. Создайте список User-Agent и случайным образом выбирайте один для каждого запроса. Используйте библиотеку fake-useragent.

    from fake_useragent import UserAgent
    ua = UserAgent()
    headers = {'User-Agent': ua.random}
    response = requests.get(url, headers=headers, proxies=proxy, timeout=10)
  • Cookie Handling: Сохранение и использование cookie, которые сайт устанавливает для вашего браузера. requests автоматически обрабатывает cookie.

    session = requests.Session() # Используем сессию для сохранения cookie
    response = session.get(url, proxies=proxy, timeout=10)
  • JavaScript Rendering: Использование selenium или playwright для выполнения JavaScript и обхода защиты, основанной на JavaScript. Эти библиотеки позволяют запускать реальный браузер и взаимодействовать с веб-страницей, как это делает пользователь. Это позволяет обойти сложные защиты, основанные на анализе поведения пользователя.

    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    
    options = Options()
    options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36")
    driver = webdriver.Chrome(options=options) # Укажите путь к ChromeDriver
    driver.get(url)
    html = driver.page_source
    driver.quit()
  • CAPTCHA Solving: Интеграция с сервисами распознавания CAPTCHA (например, 2Captcha, Anti-Captcha). Когда сайт показывает CAPTCHA, вы отправляете ее изображение в сервис распознавания, получаете текст и отправляете его на сайт.

  • Headers Spoofing: Имитация HTTP-заголовков реального браузера. Сравните заголовки, отправляемые вашим скриптом, с заголовками, отправляемыми вашим браузером, и добавьте недостающие заголовки.

    headers = {
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        'Accept-Encoding': 'gzip, deflate, br',
        'Accept-Language': 'en-US,en;q=0.5',
        'DNT': '1',
        'Connection': 'keep-alive',
        'Upgrade-Insecure-Requests': '1',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0'
    }
    response = requests.get(url, headers=headers, proxies=proxy, timeout=10)

Обход защиты от ботов – это постоянная гонка вооружений. Веб-сайты постоянно совершенствуют свои методы защиты, а разработчики – свои методы обхода.

 

Заключение:

Работа с прокси – важный навык для любого разработчика, занимающегося web scraping, автоматизацией или обходом географических ограничений. В этой статье мы рассмотрели продвинутые техники, которые помогут вам эффективно использовать прокси для решения сложных задач. Помните, что успех зависит от вашей внимательности к деталям, постоянного тестирования и готовности адаптироваться к изменяющимся условиям. Всегда соблюдайте этические нормы и уважайте условия использования веб-сайтов. 

Перейти к следующему шагу

Возникли вопросы при прочтении лекции? Задайте вопрос в комментариях

Комментарии