Geolokasi IP batch dengan Python
Perkaya sebuah daftar IP terhadap POST /v1/lookup dalam batch berisi 100, dengan asosiasi baris, output yang di-checkpoint, dan back off 429 — dipanggil langsung lewat HTTP, karena Python SDK resmi belum mencakup endpoint ini.
Sebelum Anda mulai
- Akun Watch-IP dan secret lookup key — POST /v1/lookup hanya untuk server-ke-server; jangan pernah memanggilnya dari browser atau menyematkan key-nya di sebuah klien.
- Python 3.9+.
- Daftar IP lokal yang ingin Anda perkaya — panduan ini membacanya dari sebuah CSV berisi satu IP per baris.
1. Mengapa ini menggunakan HTTP langsung, bukan SDK
watch-ip-sdk, paket Python resmi, hanya mengimplementasikan GET /v1/geo, endpoint visitor yang menghadap browser — SDK ini tidak punya method untuk POST /v1/lookup. Panduan ini memanggil API langsung dengan urllib dari standard library, mengikuti pendekatan tanpa dependensi milik SDK itu sendiri alih-alih menambah dependensi baru hanya untuk ini.
2. Baca dan validasi daftar input
Simpan posisi baris asli setiap IP agar sebuah hasil bisa dicocokkan kembali ke record asalnya — API mengembalikan hasil dalam urutan yang sama seperti saat menerima IP-nya, yang hanya membantu jika daftar Anda sendiri juga tetap dalam urutan itu.
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. Bagi menjadi batch berisi 100
POST /v1/lookup menerima 1–100 IP per panggilan dan memvalidasi seluruh batch sebelum mencari apa pun — satu alamat yang salah bentuk menggagalkan seluruh chunk, jadi validasi sintaks IP secara lokal dulu jika daftar input Anda mungkin kotor.
Python
def chunk(items, size=100):
for i in range(0, len(items), size):
yield items[i : i + size]4. Kirim setiap batch dan checkpoint hasilnya
Tulis hasil begitu setiap batch selesai, bukan menyimpan semuanya di memori sampai akhir, sehingga kegagalan di tengah daftar yang panjang tidak menghilangkan batch yang sudah berhasil. found: false berarti IP-nya valid secara sintaks tapi tidak punya entri di database — hasil yang normal, bukan error.
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) # tunggu hingga akhir jendela satu menit saat ini
results = lookup_batch(batch)
else:
raise
for result in results:
out.write(json.dumps(result) + "\n")5. Melanjutkan pekerjaan yang terhenti separuh jalan
Karena hasil ditambahkan satu batch per satu waktu, memulai ulang setelah crash hanya perlu melewati IP yang sudah tertulis di results.jsonl, bukan mengirim ulang seluruh daftar — mengirim ulang IP duplikat akan ditagih lagi, karena setiap input dalam sebuah batch diukur secara individual, bukan dihilangkan duplikatnya.
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]Error dan kasus khusus
400 berarti batch tersebut berisi lebih dari 100 IP, daftar kosong, atau ada alamat yang salah bentuk di suatu tempat di dalamnya — seluruh chunk gagal, bukan hanya entri yang salah. 403 berarti publishable key digunakan, bukan secret key. Mencampur alamat IPv4 dan IPv6 dalam batch yang sama tidak masalah; masing-masing dicari secara independen, dengan field nullable yang sama untuk keduanya.
Langkah berikutnya
Lihat referensi pencarian IP massal untuk skema respons yang persis, dan error dan rate limit untuk daftar kode status lengkap yang bisa dikembalikan endpoint ini.