ChangeMyIP sous Linux : pipeline avancé de suivi des classements par pays
Créez un pipeline planifié de vérification des classements par marché sous Linux qui fait tourner les IP de sortie ChangeMyIP, vérifie le pays de sortie à chaque contrôle et consigne des résultats diffables fiables.
Aperçu
Le suivi des classements n'est fiable que si l'IP depuis laquelle vous interrogez l'est aussi. Lorsque chaque contrôle d'une campagne multi-marchés sort via une seule adresse, les points de terminaison de recherche et d'analyse peuvent renvoyer des réponses mises en cache, personnalisées ou limitées, et les chiffres que vous présentez cessent de refléter ce que voit réellement un visiteur local.
Ce tutoriel construit un pipeline avancé et planifié de vérification des classements sous Linux qui utilise les IP de sortie ChangeMyIP par marché. Vous allez :
- confirmer le point de terminaison proxy et l'identité de sortie avant chaque lot,
- envoyer des requêtes via HTTP/HTTPS ou SOCKS5 avec gestion des nouvelles tentatives, du jitter et des délais d'attente,
- rejeter les réponses qui ne sont pas sorties du pays attendu,
- ajouter les résultats à un journal JSONL diffable et planifier la tâche avec cron,
- garder les identifiants en dehors de vos scripts et hors du contrôle de version.
ChangeMyIP fournit des proxys datacenter dédiés et partagés ainsi que des proxys résidentiels rotatifs via HTTP, SOCKS5, Shadowsocks, Trojan, DNS et WireGuard, couvrant plus de 40 pays, plus de 300 villes et plus de 1000 sous-réseaux avec une facturation mensuelle forfaitaire, ce qui en fait une couche de sortie pratique pour un crawler récurrent, marché par marché.
Prérequis
- Un hôte Linux avec accès réseau sortant (Debian/Ubuntu, Fedora ou similaire).
- Python 3.9 ou version ultérieure avec la bibliothèque
requests. curletjqpour une vérification manuelle rapide.- Un abonnement ChangeMyIP actif, ainsi que l'hôte de passerelle, le port du protocole, le nom d'utilisateur et le mot de passe indiqués dans votre tableau de bord.
- Une liste de marchés cibles (par exemple
us,gb,de,jp,br) et les pages que vous souhaitez suivre.
Choisir entre sortie datacenter et résidentielle
- Datacenter (dédié ou partagé) — l'option la plus rapide et la plus économique par contrôle. Utilisez-la pour les contrôles secondaires à gros volume, l'interrogation des sitemaps et les marchés où la personnalisation des résultats n'est pas l'objectif.
- Résidentiel (rotatif) — des adresses de FAI grand public. Utilisez-le lorsqu'une page ou un ensemble de résultats doit ressembler à un véritable visiteur local, et lorsque les plages datacenter sont contestées ou reçoivent du contenu dégradé.
- Routage mixte — envoyez les marchés géosensibles via une sortie résidentielle et gardez la longue traîne sur datacenter. Comme ChangeMyIP facture au forfait mensuel, l'ajout de volume planifié est facile à budgéter.
Quel que soit votre choix, vérifiez le pays de sortie plutôt que de le supposer.
Étapes
1. Récupérer les détails du point de terminaison et les stocker en sécurité
Connectez-vous au tableau de bord ChangeMyIP et copiez l'hôte de passerelle, le port du protocole que vous utiliserez (HTTP/HTTPS ou SOCKS5), votre nom d'utilisateur et votre mot de passe. Conservez-les dans un fichier d'environnement lisible par root plutôt que dans vos scripts :
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
Définissez CMIP_SCHEME sur socks5h lorsque le port qui vous a été attribué parle SOCKS5 et que vous voulez que le DNS soit résolu au niveau du proxy plutôt que sur votre hôte.
2. Installer la chaîne d'outils
sudo apt update
sudo apt install -y curl jq python3 python3-pip
python3 -m pip install --user requests
3. Vérifier une requête unique via le proxy
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}'
Exécutez-la trois ou quatre fois. Sur un forfait rotatif, l'IP de sortie doit changer entre les exécutions et ne doit jamais correspondre à l'adresse de votre propre FAI. Si la sortie correspond à votre propre connexion, le proxy n'est pas appliqué du tout.
4. Décrire vos marchés et cibles dans un seul fichier
{
"markets": {
"us": ["https://example.com/pricing"],
"gb": ["https://example.com/pricing"],
"de": ["https://example.com/pricing"]
}
}
Enregistrez-le sous /etc/cmip/targets.json et définissez les codes de marché pour qu'ils correspondent aux points de terminaison pays disponibles dans votre tableau de bord ChangeMyIP.
5. Écrire le pipeline avec vérification géographique à chaque contrôle
#!/usr/bin/env python3
'''Per-market rank checks through ChangeMyIP rotating proxies.'''
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()
Enregistrez-le sous /opt/cmip/rank_check.py. L'indicateur country_ok est ce qui garantit l'honnêteté de vos rapports : un contrôle sorti du mauvais pays est tout de même enregistré, mais vous pouvez l'exclure en aval.
Comme un forfait rotatif peut attribuer une IP de sortie différente à chaque requête, la vérification géographique et la récupération de la page peuvent partir d'adresses différentes. Si votre tableau de bord ChangeMyIP expose des contrôles de session ou de rotation, comme une durée de session ou un jeton de session sticky, épinglez une IP de sortie par contrôle afin que les deux requêtes partagent une adresse ; sinon, traitez country_ok comme un signal fort pour le lot plutôt que comme une garantie pour chaque récupération individuelle.
6. L'exécuter une fois au premier plan
set -a; . /etc/cmip/env; set +a
python3 /opt/cmip/rank_check.py
Inspectez le journal avant de planifier quoi que ce soit :
jq -s 'group_by(.market) | map({market: .[0].market, checks: length, ok: (map(select(.country_ok)) | length)})' /var/log/cmip/rank-checks.jsonl
7. Planifier la tâche
17 */6 * * * set -a; . /etc/cmip/env; set +a; /usr/bin/python3 /opt/cmip/rank_check.py >> /var/log/cmip/run.log 2>&1
Décalez les minutes au lieu de tout exécuter à l'heure pile, et maintenez le volume total en adéquation avec ce pour quoi votre forfait ChangeMyIP est dimensionné.
8. Comparer l'historique au lieu de relire des exécutions isolées
jq -r 'select(.country_ok) | [.ts, .market, .url] | @tsv' /var/log/cmip/rank-checks.jsonl | tail -n 40
Vérifier l'IP de sortie pour chaque point de terminaison de marché
Répétez ce bloc une fois par point de terminaison pays affiché dans votre tableau de bord ChangeMyIP, en exportant les CMIP_SCHEME, CMIP_USER, CMIP_PASS, CMIP_HOST et CMIP_PORT correspondants pour chacun :
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
Notez les pays que vous obtenez réellement. Ce sont les marchés sur lesquels vous pouvez rapporter en toute confiance.
Dépannage
| Symptôme | Cause probable | Que faire |
|---|---|---|
407 Proxy Authentication Required |
Identifiants manquants, mal saisis ou contenant des caractères nécessitant un encodage URL | Revérifiez les valeurs du tableau de bord et encodez en pourcentage les caractères réservés dans le mot de passe avant de construire l'URL du proxy, par exemple @ devient %40 |
curl: (7) ou expiration de la connexion |
Mauvais port, ou port HTTP utilisé avec un schéma SOCKS5 | Recopiez le port correspondant au protocole que vous avez sélectionné |
| Le pays de sortie n'est systématiquement pas le marché demandé | Le ciblage pays n'est pas appliqué à ce point de terminaison ou à ce port, ou la rotation a sélectionné une autre région | Utilisez le point de terminaison spécifique au pays indiqué dans votre tableau de bord et épinglez une session si ce contrôle existe |
429 ou 503 de la part du site cible |
Le rythme des requêtes est trop agressif | Augmentez le délai entre les requêtes, ajoutez du jitter et répartissez les marchés sur le planning |
| Échecs de handshake TLS | Incompatibilité entre le schéma et le port | Essayez le schéma socks5h avec le port SOCKS5 correspondant |
| Comportement différent d'une vérification manuelle dans un navigateur | Cookies, mise en cache ou user agent différent | Réutilisez une seule requests.Session par marché et gardez des en-têtes cohérents entre les exécutions |
| Le DNS semble se résoudre localement | Le schéma de proxy HTTP résout les noms sur votre hôte | Passez à socks5h pour que les résolutions aient lieu au niveau du proxy |
| Le fichier journal grossit sans limite | Absence de rotation ou de politique de rétention | Ajoutez logrotate ou élaguez les entrées plus anciennes que votre fenêtre de rétention |
Résumé
- Une vérification de classement n'est valide que lorsque vous savez de quel pays elle est sortie ; la vérification géographique n'est pas facultative à l'échelle.
- La sortie résidentielle rotative de ChangeMyIP convient aux contrôles précis par marché, tandis que la sortie datacenter dédiée ou partagée convient au travail en volume ; la facturation mensuelle forfaitaire rend le budget prévisible.
- Gardez le pipeline honnête en journalisant
country_okpour chaque enregistrement et en filtrant dessus en aval. - Vérifiez manuellement chaque point de terminaison pays avant de faire confiance à une planification automatisée, et relancez cette vérification chaque fois que vous ajoutez un marché.
- Augmentez la charge de manière responsable : un rythme régulier, des nouvelles tentatives avec jitter et une session par marché seront toujours plus performants que la force brute.