Watch-IP

Geolocalizzazione IP in batch con Python

Arricchisci un elenco di IP tramite POST /v1/lookup in batch da 100, con associazione alla riga di origine, output con checkpoint e backoff sui 429 — chiamato direttamente via HTTP, poiché l'SDK Python ufficiale non copre questo endpoint.

Prima di iniziare

  • Un account Watch-IP e una chiave segreta di ricerca — POST /v1/lookup è solo da server a server; non chiamarlo mai da un browser né distribuire la chiave in un client.
  • Python 3.9+.
  • Un elenco locale di IP da arricchire — questa guida li legge da un CSV con un IP per riga.

1. Perché si usa l'HTTP diretto invece dell'SDK

watch-ip-sdk, il pacchetto Python ufficiale, implementa solo GET /v1/geo, l'endpoint visitatore rivolto al browser — non ha alcun metodo per POST /v1/lookup. Questa guida chiama l'API direttamente con urllib dalla libreria standard, seguendo lo stesso approccio a zero dipendenze dell'SDK invece di aggiungerne una nuova solo per questo.

2. Leggi e convalida l'elenco di input

Mantieni la posizione originale di riga di ciascun IP, così un risultato può essere ricollegato al record da cui proviene — l'API restituisce i risultati nello stesso ordine in cui ha ricevuto gli IP, il che è utile solo se anche il tuo elenco resta in quell'ordine.

Python

import csv

with open("ips.csv", newline="") as f:
    ips = [row[0].strip() for row in csv.reader(f) if row and row[0].strip()]

print(f"Loaded {len(ips)} IPs")

3. Dividi in batch da 100

POST /v1/lookup accetta da 1 a 100 IP per chiamata e convalida l'intero batch prima di effettuare qualsiasi ricerca — un indirizzo malformato fa fallire l'intero blocco, quindi convalida prima localmente la sintassi degli IP se il tuo elenco di input potrebbe non essere pulito.

Python

def chunk(items, size=100):
    for i in range(0, len(items), size):
        yield items[i : i + size]

4. Invia ogni batch e salva un checkpoint dei risultati

Scrivi i risultati man mano che ogni batch si completa invece di tenere tutto in memoria fino alla fine, così un errore a metà di un elenco lungo non fa perdere i batch già riusciti. found: false significa che l'IP è sintatticamente valido ma non ha una voce nel database — un risultato normale, non un errore.

Python

import json
import time
import urllib.error
import urllib.request

API_URL = "https://api.watch-ip.com/v1/lookup"
SECRET_KEY = "YOUR_SECRET_KEY"

def lookup_batch(ips):
    request = urllib.request.Request(
        API_URL,
        data=json.dumps({"ips": ips}).encode(),
        headers={
            "Authorization": f"Bearer {SECRET_KEY}",
            "Content-Type": "application/json",
        },
    )
    with urllib.request.urlopen(request) as response:
        return json.load(response)["results"]

with open("results.jsonl", "a") as out:
    for batch in chunk(ips):
        try:
            results = lookup_batch(batch)
        except urllib.error.HTTPError as err:
            if err.code == 429:
                time.sleep(60)  # attendi il resto della finestra di un minuto in corso
                results = lookup_batch(batch)
            else:
                raise
        for result in results:
            out.write(json.dumps(result) + "\n")

5. Riprendere un lavoro parziale

Poiché i risultati vengono aggiunti un batch alla volta, riavviare dopo un crash richiede solo di saltare gli IP già scritti in results.jsonl invece di reinviare l'intero elenco — reinviare un IP duplicato viene fatturato di nuovo, poiché ogni input di un batch viene misurato individualmente e non deduplicato.

Python

done = set()
with open("results.jsonl") as f:
    for line in f:
        done.add(json.loads(line)["ip"])

remaining = [ip for ip in ips if ip not in done]

Errori e casi limite

Un 400 significa che il batch aveva più di 100 IP, un elenco vuoto, oppure un indirizzo malformato al suo interno — fallisce l'intero blocco, non solo la voce errata. Un 403 significa che è stata usata una chiave pubblicabile invece di una chiave segreta. Mischiare indirizzi IPv4 e IPv6 nello stesso batch va bene; ciascuno viene cercato in modo indipendente, con gli stessi campi nullable in entrambi i casi.

Passo successivo

Consulta il riferimento della ricerca IP in blocco per lo schema esatto della risposta, ed errori e limiti di frequenza per l'elenco completo dei codici di stato che questo endpoint può restituire.

Pagine correlate