Как маршрутизировать прокси Dataimpulse через mitmproxy на macOS для веб-скрейпинга
Один локальный слушатель mitmproxy перенаправляет все скраперы, браузеры и эмуляторы на macOS к резидентным или мобильным прокси Dataimpulse через HTTP или SOCKS5, с ротацией, ограничением скорости и опциональной TLS-инспекцией под вашим контролем.
Обзор
mitmproxy — это программируемый прокси-перехватчик с открытым исходным кодом, работающий как обычный процесс macOS. В upstream-режиме он принимает подключения от локальных клиентов на одном порту (127.0.0.1:8080) и перенаправляет этот трафик на второй прокси — в данном случае на ваш резидентный или мобильный эндпоинт Dataimpulse.
Преимущество — централизация: вы настраиваете прокси один раз, после чего любой браузер, CLI-инструмент, Python-скрипт или мобильный эмулятор на машине можно маршрутизировать через Dataimpulse без редактирования собственных настроек прокси этого инструмента. Всё проходит через единую точку, где можно ограничить параллелизм, отслеживать сбои и подтвердить, какой исходящий IP вы фактически используете.
Dataimpulse хорошо подходит для такого шаблона, потому что предлагает резидентные и мобильные эндпоинты как через HTTP, так и через SOCKS5, с оплатой по факту использования и большим пулом IP — это полезно для импульсивного сбора данных с большим объёмом, где ежемесячные обязательства не нужны. Вы можете сравнить его с другими провайдерами прокси, прежде чем выбирать.
Когда этот подход имеет смысл
| Подход | Что вы настраиваете | Лучше всего подходит для |
|---|---|---|
| Upstream-режим mitmproxy (это руководство) | Один локальный порт для всех клиентов | Несколько инструментов одновременно, централизованное ограничение и логирование |
Флаги прокси для каждого инструмента (curl -x, requests proxies=) |
Каждый инструмент отдельно | Один скрипт с минимальным количеством движущихся частей |
| Десктопные менеджеры прокси (например, Proxifier) | Правила для каждого приложения | GUI-приложения, игнорирующие системные настройки прокси |
Что вы построите
- Локальный слушатель mitmproxy на
127.0.0.1:8080 - Upstream-подключение к Dataimpulse через HTTP или SOCKS5
- Опциональный перехват TLS для конкретных хостов, которые вы хотите инспектировать
- Добавление для ограничения параллелизма, которое делает нагрузку запросов предсказуемой
- Рабочие примеры для
curl,requests, Playwright и эмулятора Android
Предварительные требования
- macOS 13 или новее с установленным Homebrew
- Аккаунт Dataimpulse, а также имя пользователя, пароль, хост шлюза и порты HTTP/SOCKS5, показанные в вашей панели управления
- Python 3.9 или новее для примеров клиентов (
python3 --version) - Уверенное владение Терминалом и базовое понимание HTTP-прокси и TLS
Как работает настройка
- mitmproxy слушает на
127.0.0.1:8080. - Ваш клиент отправляет запрос в mitmproxy, а не напрямую на целевой сайт.
- mitmproxy открывает подключение к шлюзу Dataimpulse.
- Dataimpulse назначает исходящий IP из своего пула.
- Ответ возвращается через mitmproxy к вашему клиенту.
Важны два режима, и ранний выбор между ними экономит время:
- Прозрачный проход (туннелирование): mitmproxy пересылает TLS-байты, не расшифровывая их. Никаких изменений сертификатов нигде не требуется. Включается с
--ignore-hosts '.*'. - Перехват: mitmproxy завершает TLS, чтобы читать или переписывать запросы и ответы. Требует доверия к CA-сертификату mitmproxy в macOS и в каждой клиентской среде выполнения.
Для скрейпинга, которому нужен только другой исходящий IP, прозрачный проход проще и быстрее, и он полностью избегает работы с сертификатами. Включайте перехват только для хостов, которые вам действительно нужно инспектировать.
Шаги
-
Установите mitmproxy.
brew install mitmproxy mitmdump --version -
Экспортируйте учётные данные Dataimpulse как переменные окружения, чтобы они никогда не появлялись в истории командной оболочки или в закоммиченных файлах.
export DI_USER='your-dataimpulse-username' export DI_PASS='your-dataimpulse-password' export DI_HOST='gateway-host-from-your-dashboard' export DI_HTTP_PORT='http-port-from-your-dashboard' export DI_SOCKS_PORT='socks5-port-from-your-dashboard' export DI_SESSION='scrape-macos-01'Добавьте те же строки в
~/.zshrc, если хотите, чтобы они были доступны в каждой новой оболочке, и подтвердите хост и порт, не выводя пароль:echo "${DI_HOST}:${DI_HTTP_PORT}" -
Кодируйте учётные данные, содержащие зарезервированные символы, в процентную кодировку. Символы вроде
@,:,/или#внутри пароля нарушат upstream-URL. Кодируйте только то значение, которое вы помещаете в URL.python3 -c "import os, urllib.parse; print(urllib.parse.quote(os.environ['DI_PASS'], safe=''))" -
Запустите mitmproxy в upstream-режиме прозрачного прохода через HTTP. В режиме прозрачного прохода mitmproxy туннелирует трафик без расшифровки, поэтому изменения клиентских сертификатов не требуются.
mitmdump \ --mode "upstream:http://${DI_USER}:${DI_PASS}@${DI_HOST}:${DI_HTTP_PORT}" \ --listen-port 8080 \ --ignore-hosts '.*' \ --set flow_detail=1 -
Проверьте исходящий IP. Оставьте mitmproxy работать в отдельном окне терминала и проверьте из второго окна.
curl -s -x http://127.0.0.1:8080 https://api.ipify.org echo curl -s https://api.ipify.org echoЭти два адреса должны различаться. Если они совпадают, запрос не достигает Dataimpulse — см. раздел устранения неполадок.
-
Переключите upstream на SOCKS5, когда хотите, чтобы прокси разрешал DNS удалённо, что часто предпочтительнее для геозависимых целей.
mitmdump \ --mode "upstream:socks5://${DI_USER}:${DI_PASS}@${DI_HOST}:${DI_SOCKS_PORT}" \ --listen-port 8080 \ --ignore-hosts '.*' -
Включайте перехват только для нужных хостов.
--allow-hostsограничивает расшифровку совпадающими хостами; всё остальное остаётся туннелированным и нетронутым.mitmdump \ --mode "upstream:http://${DI_USER}:${DI_PASS}@${DI_HOST}:${DI_HTTP_PORT}" \ --listen-port 8080 \ --allow-hosts 'example\.com' \ -s ./gate.py -
Доверьтесь CA-сертификату mitmproxy перед скрейпингом HTTPS-хостов через перехват. Файлы сертификатов создаются при первом запуске mitmproxy.
# First run generates ~/.mitmproxy/mitmproxy-ca-cert.pem mitmdump --listen-port 8081 & sleep 2 kill %1 sudo security add-trusted-cert -d -r trustRoot \ -k /Library/Keychains/System.keychain \ ~/.mitmproxy/mitmproxy-ca-cert.pemСреды выполнения командной строки часто игнорируют связку ключей macOS, поэтому укажите им явный bundle:
cat "$(python3 -c 'import certifi; print(certifi.where())')" \ ~/.mitmproxy/mitmproxy-ca-cert.pem > ~/.mitmproxy/ca-bundle.pem export REQUESTS_CA_BUNDLE=~/.mitmproxy/ca-bundle.pem export NODE_EXTRA_CA_CERTS=~/.mitmproxy/mitmproxy-ca-cert.pem -
Добавьте addon для ограничения параллелизма, чтобы всплеск от быстрого скрапера не перегружал шлюз. Сохраните это как
gate.pyрядом с каталогом, из которого вы запускаете mitmproxy.# gate.py — cap in-flight requests passing through mitmproxy import asyncio from mitmproxy import http class Gate: def __init__(self, limit: int = 8) -> None: self._limit = limit self._sem: asyncio.Semaphore | None = None def running(self) -> None: self._sem = asyncio.Semaphore(self._limit) async def request(self, flow: http.HTTPFlow) -> None: await self._sem.acquire() flow.metadata["gate_held"] = True def _release(self, flow: http.HTTPFlow) -> None: if flow.metadata.pop("gate_held", False): self._sem.release() def response(self, flow: http.HTTPFlow) -> None: self._release(flow) def error(self, flow: http.HTTPFlow) -> None: self._release(flow) addons = [Gate(limit=8)]Загрузите его с
-s ./gate.py. Обратите внимание, что addons видят только перехваченные потоки: если вы запускаете с--ignore-hosts '.*', подключения туннелируются, и эти хуки никогда не срабатывают. В этом случае ограничивайте параллелизм внутри вашего скрапера. -
Направьте свои инструменты на локальный слушатель. Для shell-инструментов экспортируйте стандартные переменные в терминале, из которого вы скрейпите — но не в терминале, где запущен mitmproxy, чтобы избежать прокси-петли.
export HTTP_PROXY=http://127.0.0.1:8080 export HTTPS_PROXY=http://127.0.0.1:8080 export NO_PROXY=localhost,127.0.0.1 curl -s https://httpbin.org/ipДля Python-скрипта конфигурация CA не нужна, пока вы остаётесь в режиме прозрачного прохода:
import requests LOCAL_PROXY = "http://127.0.0.1:8080" proxies = {"http": LOCAL_PROXY, "https": LOCAL_PROXY} response = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=30) response.raise_for_status() print(response.json())Для headless-браузера передайте тот же локальный прокси в контекст браузера:
from playwright.sync_api import sync_playwright LOCAL_PROXY = "http://127.0.0.1:8080" with sync_playwright() as p: browser = p.chromium.launch(headless=True, proxy={"server": LOCAL_PROXY}) page = browser.new_page() page.goto("https://httpbin.org/ip", wait_until="domcontentloaded") print(page.inner_text("body")) browser.close()Если вам также нужно скрейпить сервис, работающий на вашей собственной машине, Chromium по умолчанию обходит loopback-адреса. Добавление
args=["--proxy-bypass-list=<-loopback>"]в вызов запуска убирает это исключение. -
Захват трафика эмулятора (опционально). Мобильные эндпоинты Dataimpulse предоставляют исходящие IP уровня оператора; они сами не захватывают трафик устройства. Чтобы маршрутизировать эмулятор через этот пул, направьте эмулятор на слушатель хоста.
# Android emulator: 10.0.2.2 is the host machine adb shell settings put global http_proxy 10.0.2.2:8080 adb shell settings get global http_proxy # Reset when finished adb shell settings put global http_proxy :0Для iOS Simulator откройте Settings, выберите Wi-Fi, затем Configure Proxy, Manual и укажите сервер
127.0.0.1на порту8080. Трафик симулятора использует сетевой стек Mac, поэтому для перехвата CA также нужно установить в симуляторе. -
Очистите после завершения. Удалите сертификат перехвата и сбросьте все настройки клиентов, чтобы посторонний трафик перестал идти через mitmproxy.
sudo security delete-certificate -c mitmproxy /Library/Keychains/System.keychain unset HTTP_PROXY HTTPS_PROXY
Устранение неполадок
407 Proxy Authentication Required
В upstream-URL отсутствуют учётные данные, или зарезервированный символ в пароле нарушил URL. Повторно запустите команду процентного кодирования из шага 3 и пересоберите строку --mode с закодированным значением.
SSLCertVerificationError, CERT_AUTHORITY_INVALID или unable to get local issuer certificate
Вы включили перехват, но клиент не доверяет CA mitmproxy. Установите сертификат, как показано в шаге 8, затем задайте переменные bundle для конкретной среды выполнения (REQUESTS_CA_BUNDLE, NODE_EXTRA_CA_CERTS). Либо вернитесь в режим прозрачного прохода с --ignore-hosts '.*', если вам не нужно читать трафик.
Address already in use
Порт уже занят другим процессом. Найдите его, затем измените --listen-port, а не убивайте посторонние сервисы.
lsof -nP -iTCP:8080 -sTCP:LISTEN
Все запросы зависают или истекают по тайм-ауту
Скорее всего, вы в прокси-петле: HTTP_PROXY экспортирован в той же оболочке, которая запустила mitmproxy, поэтому собственное upstream-подключение mitmproxy отправляется обратно к нему самому. Запустите mitmproxy в чистом терминале или выполните unset HTTP_PROXY HTTPS_PROXY перед его запуском.
Запросы успешны, но исходящий IP никогда не меняется
Режим прозрачного прохода сам по себе ничего не ротирует. Поведение ротации определяется типом сессии, который вы настроили в панели управления, и тем, как ваш клиент открывает подключения. Убедитесь, что вы не закрепляете одну липкую сессию на весь запуск, и проверьте исходящий IP командой из шага 5.
Эмулятор игнорирует прокси
В эмуляторах Android 127.0.0.1 относится к самому эмулятору, а не к Mac. Используйте 10.0.2.2 и подтвердите значение с помощью adb shell settings get global http_proxy.
Цели возвращают 403 или 429
Это ограничение скорости на стороне назначения, а не сбой прокси. Уменьшите лимит gate в gate.py, добавьте задержки между запросами и убедитесь, что ваш скрейпинг соответствует условиям сайта и robots.txt.
Итоги
Теперь у вас есть единый локальный слушатель mitmproxy на macOS, который перенаправляет любой клиент к резидентным или мобильным прокси Dataimpulse через HTTP или SOCKS5, с режимом прозрачного прохода для простой ротации IP и выборочным перехватом для более глубокой инспекции. Учётные данные хранятся в переменных окружения, параллелизм ограничен addon'ом, а доверие к сертификату можно чисто добавить или удалить, когда вам больше не нужно читать зашифрованный трафик.