ChangeMyIP в Linux: продвинутый конвейер отслеживания позиций по странам
Создайте запланированный конвейер проверки позиций по рынкам в Linux, который ротирует исходящие IP-адреса ChangeMyIP, проверяет страну выхода при каждой проверке и записывает результаты, пригодные для diff-сравнения, которым можно доверять.
Обзор
Достоверность отслеживания позиций определяется тем IP-адресом, с которого вы выполняете запросы. Когда каждая проверка в мультирыночной кампании выходит через один адрес, поисковые и аналитические эндпоинты могут возвращать кэшированные, персонализированные или ограниченные по частоте ответы, и цифры, которые вы отчитываете, перестают отражать то, что на самом деле видит локальный посетитель.
В этом руководстве создаётся продвинутый запланированный конвейер проверки позиций в Linux, использующий исходящие IP-адреса ChangeMyIP для каждого рынка. Вы:
- подтвердите прокси-эндпоинт и идентичность выхода перед каждой партией;
- отправляйте запросы через HTTP/HTTPS или SOCKS5 с повторными попытками, джиттером и обработкой тайм-аутов;
- отклоняйте ответы, которые вышли не из ожидаемой страны;
- добавляйте результаты в JSONL-журнал, пригодный для diff-сравнения, и запланируйте задание через cron;
- храните учётные данные вне ваших скриптов и вне системы контроля версий.
ChangeMyIP предоставляет выделенные и общие прокси дата-центров и ротируемые резидентские прокси по HTTP, SOCKS5, Shadowsocks, Trojan, DNS и WireGuard, охватывающие более 40 стран, более 300 городов и более 1000 подсетей при фиксированной ежемесячной оплате, что делает их практичным исходящим слоем для повторяющегося краулера, работающего по рынкам.
Предварительные требования
- Linux-хост с доступом к внешней сети (Debian/Ubuntu, Fedora или аналогичный).
- Python 3.9 или новее с библиотекой
requests. curlиjqдля быстрой ручной проверки.- Активная подписка ChangeMyIP, а также хост шлюза, порт протокола, имя пользователя и пароль, указанные в вашей панели управления.
- Список целевых рынков (например,
us,gb,de,jp,br) и страницы, позиции по которым вы хотите отслеживать.
Выбор между исходящим трафиком дата-центров и резидентским
- Дата-центры (выделенные или общие) — самый быстрый и экономичный вариант для каждой проверки. Используйте его для массовых вторичных проверок, опроса карты сайта и рынков, где персонализация результатов не важна.
- Резидентские (ротируемые) — адреса потребительских интернет-провайдеров. Используйте их, когда страница или набор результатов должны выглядеть как у настоящего локального посетителя, а также когда диапазоны дата-центров блокируются или отвечают ухудшенным контентом.
- Смешанная маршрутизация — направляйте геозависимые рынки через резидентский исходящий трафик, а длинный хвост оставляйте на дата-центрах. Поскольку ChangeMyIP выставляет фиксированный ежемесячный счёт, добавление запланированного объёма легко бюджетировать.
Что бы вы ни выбрали, проверяйте страну выхода, а не предполагайте её.
Шаги
1. Соберите данные эндпоинта и сохраните их безопасно
Войдите в панель управления ChangeMyIP и скопируйте хост шлюза, порт для протокола, который будете использовать (HTTP/HTTPS или SOCKS5), ваше имя пользователя и пароль. Храните их в файле окружения, доступном для чтения только root, а не внутри ваших скриптов:
sudo install -d -m 700 /etc/cmip
sudo tee /etc/cmip/env >/dev/null <<'EOF'
CMIP_HOST=gateway-host-from-dashboard
CMIP_PORT=port-from-dashboard
CMIP_USER=your-username
CMIP_PASS=your-password
CMIP_SCHEME=http
EOF
sudo chmod 600 /etc/cmip/env
Установите CMIP_SCHEME в socks5h, когда выданный вам порт работает по SOCKS5 и вы хотите, чтобы DNS разрешался на прокси, а не на вашем хосте.
2. Установите инструментарий
sudo apt update
sudo apt install -y curl jq python3 python3-pip
python3 -m pip install --user requests
3. Проверьте один запрос через прокси
set -a; . /etc/cmip/env; set +a
curl -sS --max-time 20 \
--proxy "${CMIP_SCHEME}://${CMIP_USER}:${CMIP_PASS}@${CMIP_HOST}:${CMIP_PORT}" \
https://ipinfo.io/json | jq '{ip, city, region, country, org}'
Запустите его три-четыре раза. На ротируемом тарифе исходящий IP должен меняться между запусками и никогда не совпадать с адресом вашего собственного провайдера. Если вывод показывает ваше собственное соединение, значит, прокси вообще не применяется.
4. Опишите ваши рынки и цели в одном файле
{
"markets": {
"us": ["https://example.com/pricing"],
"gb": ["https://example.com/pricing"],
"de": ["https://example.com/pricing"]
}
}
Сохраните его как /etc/cmip/targets.json и задайте коды рынков в соответствии со страновыми эндпоинтами, доступными в вашей панели управления ChangeMyIP.
5. Напишите конвейер с геопроверкой при каждой проверке
#!/usr/bin/env python3
'''Проверки позиций по рынкам через ротируемые прокси ChangeMyIP.'''
import json
import os
import random
import time
from pathlib import Path
import requests
HOST = os.environ['CMIP_HOST']
PORT = os.environ['CMIP_PORT']
USER = os.environ['CMIP_USER']
PASS = os.environ['CMIP_PASS']
SCHEME = os.environ.get('CMIP_SCHEME', 'http')
TARGETS = json.loads(Path('/etc/cmip/targets.json').read_text())
OUT = Path('/var/log/cmip/rank-checks.jsonl')
OUT.parent.mkdir(parents=True, exist_ok=True)
def proxy_url():
return f'{SCHEME}://{USER}:{PASS}@{HOST}:{PORT}'
def get(session, url, retries=4):
last = None
for attempt in range(1, retries + 1):
try:
resp = session.get(url, timeout=25)
resp.raise_for_status()
return resp.text
except requests.RequestException as exc:
last = exc
time.sleep(min(2 ** attempt + random.random(), 30))
raise last
def run():
for market, urls in TARGETS['markets'].items():
session = requests.Session()
session.proxies = {'http': proxy_url(), 'https': proxy_url()}
session.headers['User-Agent'] = (
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 '
'(KHTML, like Gecko) Chrome/124.0 Safari/537.36'
)
try:
geo = json.loads(get(session, 'https://ipinfo.io/json'))
exit_country = (geo.get('country') or '').lower()
except (requests.RequestException, json.JSONDecodeError) as exc:
print(f'{market}: geo check failed: {exc}')
continue
for url in urls:
record = {
'ts': time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()),
'market': market,
'url': url,
'exit_ip': geo.get('ip'),
'exit_country': exit_country,
'country_ok': exit_country == market,
}
try:
body = get(session, url)
record['bytes'] = len(body)
record['status'] = 'ok'
except requests.RequestException as exc:
record['status'] = type(exc).__name__
with OUT.open('a') as fh:
fh.write(json.dumps(record) + '\n')
print(record)
if __name__ == '__main__':
run()
Сохраните его как /opt/cmip/rank_check.py. Флаг country_ok — это то, что делает вашу отчётность честной: проверка, вышедшая не из той страны, всё равно записывается, но вы можете исключить её на последующих этапах.
Поскольку ротируемый тариф может выдавать разный исходящий IP для каждого запроса, геопроверка и загрузка страницы могут выходить с разных адресов. Если ваша панель управления ChangeMyIP предоставляет управление сессиями или ротацией, например длину сессии или токен закреплённой сессии, закрепите один исходящий IP на проверку, чтобы оба запроса использовали один адрес; в противном случае рассматривайте country_ok как сильный сигнал для партии, а не как гарантию для каждой отдельной загрузки.
6. Запустите его один раз в foreground
set -a; . /etc/cmip/env; set +a
python3 /opt/cmip/rank_check.py
Проверьте журнал, прежде чем что-либо планировать:
jq -s 'group_by(.market) | map({market: .[0].market, checks: length, ok: (map(select(.country_ok)) | length)})' /var/log/cmip/rank-checks.jsonl
7. Запланируйте задание
17 */6 * * * set -a; . /etc/cmip/env; set +a; /usr/bin/python3 /opt/cmip/rank_check.py >> /var/log/cmip/run.log 2>&1
Разнесите минуты запуска вместо того, чтобы запускать всё ровно в час, и держите общий объём в пределах, на которые рассчитан ваш тариф ChangeMyIP.
8. Сравнивайте историю через diff, а не перечитывайте отдельные запуски
jq -r 'select(.country_ok) | [.ts, .market, .url] | @tsv' /var/log/cmip/rank-checks.jsonl | tail -n 40
Проверьте исходящий IP для каждого рыночного эндпоинта
Повторите этот блок по одному разу для каждого странового эндпоинта, показанного в вашей панели управления ChangeMyIP, экспортируя соответствующие CMIP_SCHEME, CMIP_USER, CMIP_PASS, CMIP_HOST и CMIP_PORT для каждого:
set -a; . /etc/cmip/env; set +a
for attempt in 1 2 3; do
curl -sS --max-time 20 \
--proxy "${CMIP_SCHEME}://${CMIP_USER}:${CMIP_PASS}@${CMIP_HOST}:${CMIP_PORT}" \
https://ipinfo.io/json | jq -r '[.country, .city, .ip, .org] | @tsv'
done
Запишите страны, которые вы действительно получаете. Это рынки, по которым вы можете отчитываться с уверенностью.
Устранение неполадок
| Симптом | Вероятная причина | Что делать |
|---|---|---|
407 Proxy Authentication Required |
Учётные данные отсутствуют, введены с ошибкой или содержат символы, требующие URL-кодирования | Перепроверьте значения в панели управления и выполните процентное кодирование зарезервированных символов в пароле перед сборкой URL прокси, например @ становится %40 |
curl: (7) или тайм-аут соединения |
Неверный порт или HTTP-порт, используемый со схемой SOCKS5 | Заново скопируйте порт, соответствующий выбранному протоколу |
| Страна выхода постоянно не та, которую вы запрашивали | Целевая страна не применяется к этому эндпоинту или порту, либо ротация выбрала другой регион | Используйте страновой эндпоинт, указанный в вашей панели управления, и закрепите сессию, если такой элемент управления есть |
429 или 503 от целевого сайта |
Слишком агрессивный темп запросов | Увеличьте задержку между запросами, добавьте джиттер и распределите рынки по расписанию |
| Сбои TLS-рукопожатия | Несовпадение схемы и порта | Попробуйте схему socks5h с соответствующим портом SOCKS5 |
| Поведение отличается от ручной проверки в браузере | Cookies, кэширование или другой user agent | Переиспользуйте один requests.Session на рынок и поддерживайте согласованность заголовков между запусками |
| Похоже, DNS разрешается локально | Схема HTTP-прокси разрешает имена на вашем хосте | Переключитесь на socks5h, чтобы поиск выполнялся на прокси |
| Файл журнала растёт без ограничений | Нет политики ротации или хранения | Добавьте logrotate или удаляйте записи старше вашего окна хранения |
Итог
- Проверка позиций действительна только тогда, когда вы знаете, из какой страны она вышла; геопроверка не является опциональной при масштабировании.
- Ротируемый резидентский исходящий трафик ChangeMyIP подходит для проверок с точностью до рынка, а выделенный или общий исходящий трафик дата-центров — для объёмной работы; фиксированная ежемесячная оплата делает бюджет предсказуемым.
- Сохраняйте честность конвейера, записывая
country_okдля каждой записи и фильтруя по нему на последующих этапах. - Проверяйте каждый страновой эндпоинт вручную, прежде чем доверять автоматическому расписанию, и повторяйте эту проверку всякий раз, когда добавляете рынок.
- Наращивайте нагрузку ответственно: стабильный темп, повторные попытки с джиттером и одна сессия на рынок всегда превзойдут грубую силу.