wayback-cdx-cloud-ip-workaround

Par divinevideo · divine-mobile

Résoudre le problème de l'API CDX de Wayback Machine qui renvoie des résultats vides ou expire depuis des IP cloud/datacenter (Cloud Run, AWS Lambda, GCE, etc.) alors qu'elle fonctionne correctement en local. À utiliser quand : (1) les requêtes CDX expirent ou renvoient 0 octet depuis Cloud Run/les fonctions cloud mais fonctionnent depuis la machine locale, (2) `urllib.request.urlopen` expire pour web.archive.org depuis un serveur, (3) l'API CDX de Wayback Machine renvoie silencieusement un résultat vide depuis des IP datacenter sans erreur HTTP, (4) il faut exécuter des scripts dépendant du CDX sur Cloud Run ou un environnement cloud similaire. Contournement : récupérer les données en local, les uploader dans un stockage cloud, les importer sur le cloud compute.

npx skills add https://github.com/divinevideo/divine-mobile --skill wayback-cdx-cloud-ip-workaround

Wayback CDX API : Contournement pour IP Cloud/Datacenter

Problème

L'API CDX de la Wayback Machine (web.archive.org/cdx/search/cdx) refuse silencieusement de servir les données aux requêtes provenant des plages IP des fournisseurs cloud (Google Cloud Run, AWS, GCE, etc.). Il n'y a pas de code d'erreur HTTP — les requêtes expirent ou retournent 0 octets. Les mêmes requêtes fonctionnent parfaitement depuis des IPs résidentielles/locales.

Contexte / Conditions de déclenchement

  • L'API CDX retourne vide (0 octets) ou expire depuis Cloud Run, Lambda, GCE, etc.
  • La même requête via curl sur une machine locale retourne les données attendues
  • Aucun code d'erreur HTTP (ni 429, ni 403) — juste vide ou timeout
  • Les autres API externes (Common Crawl, Arctic Shift, Arquivo.pt) fonctionnent bien depuis la même instance cloud
  • Même avec VPC connector + IP statique configurée, CDX échoue toujours
  • Augmenter les timeouts et les tentatives ne aide pas

Solution

Le schéma : Récupération locale → Stockage cloud → Import cloud

Puisque CDX ne répond pas aux IPs cloud, divisez le workflow :

  1. Récupération locale : Exécutez les requêtes CDX depuis votre machine locale, sauvegardez les résultats dans un fichier
  2. Upload vers stockage cloud : gsutil cp le fichier vers GCS (ou S3, etc.)
  3. Import sur cloud : Faites lire votre job Cloud Run depuis le stockage cloud au lieu de CDX

Implémentation

Étape 1 : Script de récupération locale

# Exécutez ceci localement — CDX fonctionne depuis les IPs résidentielles
import urllib.request, urllib.parse

CDX = 'https://web.archive.org/cdx/search/cdx'
results = set()
resume_key = None

while True:
    params = {
        'url': 'example.com/path/*',
        'output': 'text',
        'fl': 'original',
        'filter': 'statuscode:200',
        'limit': '10000',
        'showResumeKey': 'true',
    }
    if resume_key:
        params['resumeKey'] = resume_key

    url = f"{CDX}?{urllib.parse.urlencode(params)}"
    req = urllib.request.Request(url, headers={'User-Agent': 'MyBot/0.1'})
    with urllib.request.urlopen(req, timeout=120) as resp:
        raw = resp.read().decode('utf-8', errors='replace')

    parts = raw.rstrip().rsplit('\n\n', 1)
    data_lines = parts[0].strip().split('\n')
    resume_key = parts[1].strip() if len(parts) == 2 else None

    for line in data_lines:
        results.add(process_line(line))  # Extrayez ce dont vous avez besoin

    if not resume_key or len(data_lines) < 10000:
        break
    time.sleep(3)

# Sauvegardez dans un fichier
with open('/tmp/results.txt', 'w') as f:
    for item in sorted(results):
        f.write(f'{item}\n')

Étape 2 : Upload vers GCS

gsutil cp /tmp/results.txt gs://my-bucket/imports/results.txt

Étape 3 : Job Cloud Run avec flag --from-gcs

def load_from_gcs(gcs_path: str) -> set[str]:
    """Chargez les IDs depuis un fichier texte GCS."""
    import subprocess
    result = subprocess.run(
        ["gsutil", "cp", gcs_path, "/tmp/results.txt"],
        capture_output=True, text=True, timeout=120
    )
    if result.returncode != 0:
        raise RuntimeError(f"gsutil failed: {result.stderr}")

    items = set()
    with open("/tmp/results.txt") as f:
        for line in f:
            items.add(line.strip())
    return items

# Dans main() :
parser.add_argument("--from-gcs", type=str, default=None,
                    help="Import from GCS file instead of CDX")

if args.from_gcs:
    items = load_from_gcs(args.from_gcs)
else:
    items = fetch_from_cdx(delay=args.delay)

Étape 4 : Déployez avec --from-gcs

gcloud run jobs deploy my-job \
    --args="-m,my_module,--from-gcs,gs://my-bucket/imports/results.txt" \
    ...

Vérification

  • La récupération locale se termine avec succès avec le volume de données attendu
  • Le fichier s'upload vers GCS sans erreurs
  • Le job Cloud Run lit depuis GCS et importe vers la base de données
  • gsutil ls -l gs://my-bucket/imports/results.txt affiche la taille de fichier attendue

Exemple

Cas réel : Récupération de 312 427 vine IDs depuis les captures oEmbed de Wayback CDX.

  • CDX a échoué depuis Cloud Run (4 tentatives sur plusieurs déploiements, tous retournant 0 octets)
  • La récupération locale s'est terminée en ~4 minutes avec pagination par resumeKey
  • Uploaded fichier texte de 3,6 MB vers GCS
  • Cloud Run a importé 170 108 nouveaux IDs depuis GCS en ~10 minutes

Notes

  • Cela affecte web.archive.org spécifiquement. Les autres serveurs CDX (index.commoncrawl.org) fonctionnent bien depuis les IPs cloud
  • The Internet Archive peut mettre en whitelist des IPs spécifiques sur demande — contactez-les si vous avez un cas d'usage archival légitime
  • Même avec une IP statique whitelistée via VPC connector, l'API CDX peut ne toujours pas répondre (la whitelisting peut s'appliquer au téléchargement, pas à CDX)
  • collapse=urlkey et matchType=prefix sont plus susceptibles d'échouer que les requêtes wildcard simples, mais même les wildcards échouent depuis les IPs cloud
  • Ce contournement ajoute une étape manuelle (récupération locale + upload) mais est fiable et ne doit être fait qu'une fois par source de données
  • Pour les données qui changent fréquemment, envisagez de planifier la récupération locale via cron et d'automatiser l'upload vers GCS

Références

Skills similaires