DR massal untuk daftar klien, sebagai pekerjaan Python sepanjang 40 baris
Anda memiliki spreadsheet domain dan dasbor yang membutuhkan satu angka per baris. Pemeriksa domain backlink untuk pekerjaan itu sebagian besar adalah infrastruktur, dan skrip ini adalah infrastrukturnya.

Skripnya
Skrip ini membaca domains.txt, mengirim 200 domain per permintaan, menyimpan setiap respons mentah di SQLite, dan mencetak berapa biaya jalannya. Kami menyimpan seluruh payload karena nama field paling baik disalin dari respons nyata, bukan dari postingan blog.
import os, sqlite3, time, json, requests
BASE = "https://seomasters.dev/api.php"
KEY = os.environ["SEO_API_KEY"]
BATCH = 200
db = sqlite3.connect("dr.db")
db.execute("create table if not exists raw (ts int, batch text, body text)")
domains = [d.strip() for d in open("domains.txt") if d.strip()]
spent = 0
for i in range(0, len(domains), BATCH):
chunk = domains[i:i + BATCH]
for attempt in range(4):
try:
r = requests.get(BASE, timeout=30,
params={"action": "bulk_dr", "domains": ",".join(chunk)},
headers={"Authorization": "Bearer " + KEY})
break
except requests.RequestException:
time.sleep(2 ** attempt)
else:
raise SystemExit(f"network gave up at batch {i}")
if r.status_code in (401, 402):
raise SystemExit(f"HTTP {r.status_code}: fix the key or top up, do not retry")
body = r.json()
if not body.get("ok"):
raise SystemExit(f"ok=false at batch {i}: {json.dumps(body)[:300]}")
db.execute("insert into raw values (?,?,?)", (int(time.time()), str(i), r.text))
db.commit()
print(body.get("_credits"))Apa yang dilakukan setiap bagian
action=bulk_dr
Satu kredit per panggilan. Batas yang didokumentasikan adalah 2.000 domain per panggilan.
domains=
Parameter GET di sini. Endpoint juga menerima body POST, yang merupakan pilihan yang lebih baik ketika daftar menjadi panjang. Uji pemisah dengan dua domain sebelum menjalankan penuh.
BATCH = 200
Kebiasaan kami, bukan batas: 200 domain pendek menjaga URL tetap jauh di bawah batas proxy umum.
_credits
Hadir pada respons yang diautentikasi: biaya panggilan dan sisa yang tersisa. Mencetaknya setiap batch adalah jejak audit termurah.
Kolom body mentah
Anda menguraikannya nanti, sekali saja, berdasarkan sampel yang disimpan. Perubahan skema di sisi kami kemudian hanya membutuhkan satu kueri, bukan menjalankan ulang seluruh daftar.

Jalankan hipotetis, dengan aritmetika
Ini adalah contoh, bukan cerita pelanggan. Bayangkan sebuah agensi yang melacak 1.800 domain klien dan prospek di Google Sheet dan ingin DR diperbarui setiap hari Senin.
Pada 200 domain per batch, itu adalah 9 permintaan. Sembilan permintaan dengan 1 kredit masing-masing adalah 9 kredit, atau $0,0009 per jalanan, dan selama 52 hari Senin totalnya adalah 468 kredit, yang dibulatkan menjadi kurang dari lima sen.
Biaya bukan kendalanya. Kesegaran adalah kendalanya. Indeks dibangun ulang sekitar bulanan, sehingga jalanan mingguan akan menampilkan nilai yang sama tiga minggu dari empat, dan jalanan bulanan menangkap pergerakan yang sama dengan sekitar seperempat panggilan.
Jadi jalankan secara bulanan dan simpan spreadsheet mingguan untuk edit manusia. Detail mengapa skor bisa tetap diam ada di referensi DR.
Hal-hal yang salah dalam skrip ini
| Gejala | Penyebab | Perbaikan |
|---|---|---|
SystemExit: HTTP 402 | Saldo nol | Isi ulang dari halaman akun, jalankan ulang; batch yang selesai sudah ada di SQLite |
SystemExit: HTTP 401 | Var lingkungan kosong atau salah ketik kunci | Cetak len(KEY) dan periksa awalan sk_ |
ok=false pada batch 3 | Nilai buruk dalam daftar, seperti URL lengkap | Hapus skema dan path sebelum mengirim, lihat tabel error |
| DR sama dengan minggu lalu | Indeks belum dibangun ulang | Diharapkan; bandingkan secara bulanan |
| URL panjang ditolak | Batch terlalu besar untuk GET | Turunkan BATCH atau pindah ke body POST |
Ukuran batch, GET dan POST untuk daftar panjang
Batasnya adalah 2.000 domain per panggilan, dan skrip mengirim sepersepuluh dari itu. Setiap panggilan membutuhkan kredit datar yang sama, jadi ukuran batch adalah pertanyaan kegagalan dan payload, bukan harga.
Mengapa 200 dan bukan 2.000
Batch yang lebih kecil gagal dengan murah. Jika jalanan berhenti di tengah, ekor yang tersisa untuk diulang hanya sepanjang satu batch, bukan sepanjang satu daftar.
Daftar yang lebih pendek juga menjaga setiap body yang disimpan cukup kecil untuk dipindai secara visual ketika sebuah angka terlihat salah, dan itu lebih penting daripada beberapa panggilan yang disimpan.
Jika nanti Anda meningkatkan ukuran batch, lakukan sekali, dalam satu konstanta, dan jalankan ulang pengujian dua domain. Angka yang lebih besar bukan alasan untuk melewatkan pengujian.
Rencanakan batch terhadap panjang jalanan yang dapat Anda toleransi, bukan terhadap batas. Pekerjaan malam yang harus selesai sebelum laporan pagi dapat menanggung batch yang lebih kecil dan lebih aman daripada pengisian ulang satu kali.
GET untuk daftar pendek, POST untuk daftar panjang
Bentuk GET menempatkan setiap domain ke dalam URL. Itu berhasil sampai proxy atau baris log memotong kueri, itulah sebabnya tabel di atas mengatakan untuk menurunkan batch terlebih dahulu. Ketika daftar tumbuh, kirim nilai domains yang sama dalam body POST.
Uji pemisah dan pengkodean dengan dua domain sebelum menjalankan penuh. Koma yang tersesat muncul di batch pertama, dan lebih murah untuk melihatnya di sana.
Body POST juga menjaga daftar keluar dari log akses yang banyak host simpan secara default. Itu adalah keuntungan privasi kecil untuk daftar klien, dan itu membutuhkan satu baris header tambahan dalam skrip.
Ketika Anda beralih ke POST, pertahankan versi GET skrip sebagai cadangan untuk daftar pendek. Dua jalur kode terdengar berat, tetapi satu fungsi kecil yang memilih salah satu berdasarkan panjang mudah dibaca dan mudah diuji.
Potong dan hapus duplikat sebelum permintaan pertama
Hapus spasi, lowercase host dan hapus duplikat sebelum apa pun meninggalkan mesin Anda. Duplikat memakan ruang di bawah batas 2.000 domain, dan mereka membuat jumlah di spreadsheet Anda tidak cocok dengan jumlah di respons.
Pilih satu aturan untuk www. dan terapkan dalam satu fungsi, sehingga situs yang sama tidak pernah dicari dengan dua ejaan. Setiap pemeriksa domain backlink yang diskalakan melampaui beberapa ratus nama membutuhkan disiplin itu.
Apa yang harus dikatakan log jalanan
Cetak nilai _credits setelah setiap batch, dan tulis nomor batch, jumlah domain dan waktu di sampingnya. Tiga angka itu menjawab hampir setiap pertanyaan yang akan ditanyakan pembaca keuangan tentang jalanan.
Jalanan yang tidak mencetak apa pun sampai akhir memberi Anda tidak ada petunjuk ketika macet. Satu baris per batch murah, dan itu mengubah hang diam menjadi nomor batch yang bisa Anda sebut.
Simpan log di folder yang sama dengan file SQLite, sehingga satu cadangan menyalin keduanya. Log yang hidup di tempat lain adalah yang hilang selama insiden.

Tiga ekstensi yang layak untuk sore hari
Simpan nomor batch di samping timestamp. Itu sudah ada di tabel di atas, dan itu memungkinkan Anda menjalankan ulang hanya batch yang gagal setelah 402 di tengah jalanan.
Tulis tampilan kecil di atas tabel mentah setelah Anda memeriksa respons nyata: domain, skor, diambil-waktu. Dasbor membaca tampilan, dan kolom mentah tetap sebagai bukti Anda jika sebuah angka dipertanyakan.
Jalankan dari GitHub Actions atau cron biasa di VPS kecil. Keduanya bagus. Yang penting adalah pekerjaan keluar dengan non-nol pada kegagalan apa pun, karena kegagalan diam terlihat seperti grafik usang tiga minggu kemudian.
Mengurutkan output adalah masalah front-end. Urutkan portofolio berdasarkan skor, bucket, atau bandingkan dengan dr_distribution (1 kredit) untuk melihat di mana setiap klien berada di antara semua 181.132.097 domain.
Pergeseran field dan tabel mentah
Pekerjaan jangka panjang gagal diam-diam ketika field berubah bentuk. Kolom mentah ada agar kegagalan tetap keras dan murah untuk diperbaiki.
Simpan body mentah terlebih dahulu
Kolom mentah adalah jaring pengaman. Jika field diganti namanya atau yang baru muncul, Anda menjalankan ulang kueri di atas respons yang disimpan daripada membayar seluruh daftar lagi. Menguraikan nanti murah, sementara membeli ulang tidak.
Simpan satu sampel yang disimpan per minggu dalam file sendiri juga. Ketika parsing rusak, Anda membandingkan sampel minggu ini dengan yang terakhir berhasil.
Tulis body persis seperti diterima, tanpa pretty-printing dan tanpa trimming. Perubahan apa pun yang Anda buat pada teks sebelum menyimpannya adalah perubahan yang tidak dapat Anda batalkan nanti.
Seperti apa pergeseran dalam praktik
Katakan dasbor tiba-tiba menampilkan skor kosong untuk satu batch. Baris mentah masih ada. Anda membukanya, membandingkan kuncinya dengan sampel minggu lalu, dan menemukan perbedaannya dalam beberapa menit.
Perbaikannya kemudian adalah satu baris dalam tampilan, bukan menjalankan ulang seluruh daftar. Itulah seluruh poin menyimpan body.
Simpan catatan singkat di samping tampilan yang mengatakan field mana yang dibacanya dan kapan Anda terakhir memeriksanya terhadap respons nyata. Catatan membutuhkan satu menit untuk ditulis dan menghemat pencarian panjang nanti.
Urutkan migrasi dengan data
Buat tabel mentah sebelum tampilan, dan tampilan sebelum kueri dasbor apa pun. Simpan pernyataan create dalam satu file, jalankan secara berurutan dan catat nomor batch dengan setiap baris.
Database terpisah per klien bergeser sama seperti satu database bersama. Aturan tetap sama: satu body yang disimpan per panggilan, dan satu tempat untuk menguraikannya.
Simpan parser di dekat pengujian
Letakkan fungsi parse di repositori yang sama dengan pengujian yang membaca satu body yang disimpan. Pengujian adalah tempat di mana field yang bergeser pertama kali muncul, jauh sebelum grafik melakukannya.
Beri nama field yang diharapkan parser dalam satu konstanta di dekat bagian atas file. Peninjau kemudian dapat melihat setiap ketergantungan pada bentuk respons dalam satu layar.
Jalankan pertama, secara berurutan
- 1
Uji satu domain
Panggil
bulk_drdengan satu domain yang Anda ketahui, dan baca seluruh respons. Tuliskan kuncinya sebelum Anda menulis kode parsing apa pun. - 2
Jalankan dua batch
Beri skrip daftar 400 domain, sehingga tepat dua batch berjalan. Periksa apakah penurunan
_creditscocok dengan dua panggilan dengan satu kredit masing-masing. - 3
Hitung baris yang disimpan
Buka file SQLite dan bandingkan jumlah baris dengan jumlah batch. Ketidakcocokan berarti batch dilewati atau disimpan dua kali, dan Anda mengetahuinya sebelum dasbor melakukannya.
- 4
Jadwalkan daftar penuh
Hanya setelah pengujian bersih, tambahkan daftar penuh dan penjadwal. Pertahankan keluaran non-nol, sehingga kegagalan keras pada malam pertama.
Sebelum Anda menjadwalkannya
- Hapus duplikat dan lowercase daftar terlebih dahulu
- Putuskan sekali, dalam satu fungsi, apakah
www.tetap atau pergi - Simpan kunci di toko rahasia, bukan di crontab
- Beri peringatan pada kode keluar non-nol
- Jalankan angka anggaran kredit untuk volume Anda sendiri