Cara Menangani CAPTCHA di undetected-chromedriver (Python)

undetected-chromedriver menambal Chrome supaya flag otomatisasi berhenti bocor. Itu membuat Anda bisa masuk ke halaman. Itu tidak membuat Anda melewati checkbox reCAPTCHA, karena widget bukan pemeriksaan fingerprint, melainkan syarat token. Captcha di undetected-chromedriver tetap harus dipecahkan dan jawabannya disuntikkan ke DOM.
Empat langkah: jalankan driver yang sudah ditambal, baca sitekey dari halaman, pecahkan secara lokal, taruh token di tempat yang diharapkan halaman. Berikut semuanya dalam Python.
Apa yang dilakukan dan tidak dilakukan undetected-chromedriver
| Sinyal | Ditangani oleh driver |
|---|---|
navigator.webdriver dan sinyal khas CDP | Ya |
| Binary yang ditambal sehingga driver tidak terdeteksi sebagai driver | Ya |
| Checkbox reCAPTCHA v2 pada formulir login | Tidak |
| Tantangan v2 tak terlihat atau v3 yang dipicu oleh halaman | Tidak |
| Widget Turnstile | Tidak |
Perbedaan ini penting karena saran umum untuk scraper yang diblokir adalah “tambahkan stealth”. Jika sebuah widget tampil di layar, sebanyak apa pun stealth tidak akan menghilangkannya. Anda butuh token.
Apa yang Anda butuhkan
- Chrome terpasang, dan CapSkip berjalan di
127.0.0.1:8080. Halaman panduan penyiapan membahas aplikasinya. - Python 3.10 atau lebih baru.
- Tiga paket.
# the patched driver, selenium itself, and the local solver pip install undetected-chromedriver selenium capskip
Langkah 1: jalankan driver yang sudah ditambal
Impor sebagai uc dan bangun browser dengan cara yang sama seperti Selenium biasa. Options berasal dari uc.ChromeOptions(), bukan milik Selenium, karena library menambalnya dalam prosesnya:
# pip install undetected-chromedriver
import undetected_chromedriver as uc
options = uc.ChromeOptions()
options.add_argument("--window-size=1280,800")
# use_subprocess keeps the patched binary alive long enough
# to shut down cleanly on Windows.
driver = uc.Chrome(options=options, use_subprocess=True)
driver.get("https://example.com/login")Jangan menumpuk plugin stealth lain di atasnya. Dua patcher yang berebut properti yang sama adalah sinyal deteksi tersendiri, dan itu alasan umum kenapa setup yang tadinya bekerja tiba-tiba berhenti.
Langkah 2: baca sitekey dari halaman
sitekey adalah atribut publik pada elemen widget. Bacalah dari DOM langsung alih-alih menuliskannya secara hardcode, karena banyak situs merotasi key per lingkungan:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# The widget is injected by script, so wait for it.
widget = WebDriverWait(driver, 20).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "[data-sitekey]"))
)
sitekey = widget.get_attribute("data-sitekey")
page_url = driver.current_url
print(sitekey)Gunakan driver.current_url alih-alih URL yang Anda minta. Jika situs mengalihkan Anda ke jalur tantangan, pemecah harus diberi tahu halaman yang benar-benar Anda datangi.
Langkah 3: pecahkan secara lokal
CapSkip berjalan di komputer Anda sendiri, jadi pemecahannya adalah panggilan ke localhost. Tanpa akun, tanpa tagihan per pemecahan, tidak ada yang keluar dari mesin Anda selain sitekey dan URL halaman:
# pip install capskip
from capskip import CapSkip
solver = CapSkip(
host="127.0.0.1",
port=8080,
recaptchaTimeout=300, # seconds, also covers Turnstile
)
result = solver.recaptcha(sitekey=sitekey, url=page_url)
token = result["code"] # the g-recaptcha-response valueVarian adalah opsi, bukan metode yang berbeda. Tambahkan invisible=1 untuk widget v2 tak terlihat, version="v3" dengan action untuk v3, dan enterprise=1 untuk produk Enterprise.
Langkah 4: suntikkan token dan picu callback
Token harus masuk ke textarea tersembunyi g-recaptcha-response . Itu saja sudah cukup untuk submit formulir biasa, karena field tersebut ikut terkirim bersama sisa formulir:
driver.execute_script(
"document.getElementById('g-recaptcha-response')"
".innerHTML = arguments[0];",
token,
)
driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click()Aplikasi single-page berbeda. Aplikasi seperti itu tidak pernah membaca textarea, melainkan menunggu callback milik widget untuk menyerahkan token. Nama fungsinya dideklarasikan pada elemen, jadi Anda bisa memanggilnya langsung:
callback = widget.get_attribute("data-callback")
if callback:
# Call the page's own handler with the token, exactly as
# the widget would have done.
driver.execute_script(f"{callback}(arguments[0]);", token)Jika tidak terjadi apa-apa setelah injeksi dan tidak ada data-callback, berarti halaman memasang callback lewat JavaScript, bukan lewat markup. Halaman pemecah callback reCAPTCHA v2 membahas cara menemukannya dalam kasus itu.
Turnstile di driver yang sama
Cloudflare Turnstile bekerja dengan cara yang sama, hanya dua nama yang berubah. Field responsnya adalah cf-turnstile-response, dan berupa input, bukan textarea:
result = solver.turnstile(sitekey=sitekey, url=page_url)
driver.execute_script(
"document.querySelector('[name=cf-turnstile-response]')"
".value = arguments[0];",
result["code"],
)Itu mencakup widget yang tertanam di dalam formulir. Tantangan interstitial satu halaman penuh memerlukan dua nilai tambahan dan user agent yang dipakai saat pemecahan, yang dijelaskan halaman pemecah Turnstile tersebut.
Contoh lengkap yang berfungsi
# pip install undetected-chromedriver selenium capskip
import undetected_chromedriver as uc
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from capskip import (
CapSkip, NetworkException, ApiException, TimeoutException,
)
URL = "https://example.com/login"
solver = CapSkip(host="127.0.0.1", port=8080)
driver = uc.Chrome(options=uc.ChromeOptions(), use_subprocess=True)
try:
driver.get(URL)
widget = WebDriverWait(driver, 20).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "[data-sitekey]"))
)
sitekey = widget.get_attribute("data-sitekey")
result = solver.recaptcha(sitekey=sitekey, url=driver.current_url)
driver.execute_script(
"document.getElementById('g-recaptcha-response')"
".innerHTML = arguments[0];",
result["code"],
)
callback = widget.get_attribute("data-callback")
if callback:
driver.execute_script(f"{callback}(arguments[0]);", result["code"])
else:
driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click()
except NetworkException:
print("CapSkip is not running on 127.0.0.1:8080")
except (ApiException, TimeoutException) as err:
print(f"solve failed: {err}")
finally:
driver.quit() # always, or the patched binary lingersPecahkan dan kirim dalam satu proses. Token reCAPTCHA diterima kira-kira dua menit, jadi skrip yang memecahkan, lalu mengerjakan hal lain selama tiga puluh detik, lalu mengirim, masih aman. Skrip yang mengantrekan token untuk dipakai nanti tidak.
Kesalahan umum
| Apa yang Anda lihat | Penyebab | Perbaiki |
|---|---|---|
This version of ChromeDriver only supports Chrome version N | Driver yang ditambal salah menebak versi mayor Chrome | Berikan secara eksplisit: uc.Chrome(version_main=N) dengan N adalah versi mayor Chrome yang terpasang |
OSError: [WinError 6] The handle is invalid saat keluar | Driver terkena garbage collection sebelum sempat dimatikan | Panggil driver.quit() di dalam blok finally dan pertahankan use_subprocess=True |
NoSuchElementException saat mencari [data-sitekey] | Widget berada di dalam iframe, atau belum dirender | Tunggu seperti di atas. Untuk iframe, baca saja sitekey dari src query string iframe tersebut |
ERROR_GOOGLEKEY | sitekey kosong atau terpotong sampai ke pemecah | Cetak nilainya sebelum memecahkan. Lihat memperbaiki ERROR_GOOGLEKEY |
NetworkException | CapSkip tidak berjalan, atau portnya berbeda | Jalankan aplikasinya dan periksa port di pengaturannya |
| Token disuntikkan, formulir tetap ditolak | Halaman memakai callback dan tidak pernah membaca textarea | Panggil data-callback dengan token tersebut |
Setiap kode error dan parameter tercantum di dokumentasi API.
Pertanyaan yang sering diajukan
Apakah undetected-chromedriver memecahkan CAPTCHA dengan sendirinya?
Tidak. Library ini menyembunyikan sinyal otomatisasi yang membuat browser ditandai. Widget yang sudah dirender tetap mengharapkan token yang valid, jadi Anda memecahkannya dan menyuntikkan hasilnya. Kedua tugas itu saling melengkapi, bukan saling menggantikan.
Bisakah saya menjalankannya dalam mode headless?
Bisa, dengan uc.Chrome(headless=True), yang menerapkan patch headless milik library itu sendiri alih-alih flag Selenium. Harapkan lebih banyak tantangan dibanding mode headed. Injeksi token sendiri bekerja identik pada keduanya.
Apakah saya perlu proxy untuk pemecahannya?
Hanya jika browser memang sudah memakai proxy. Kirim proxy yang sama sebagai proxy={"type": "HTTPS", "uri": "user:pass@host:port"} agar pemecahan dan pengiriman berbagi jalur jaringan yang sama. Proxy berlaku untuk reCAPTCHA, Turnstile dan GeeTest, tidak pernah untuk CAPTCHA gambar.
Apakah ini juga bekerja dengan Selenium biasa?
Ya. Langkah 2 sampai 4 adalah panggilan WebDriver biasa, jadi semuanya berjalan tanpa perubahan di Selenium standar, di Selenium Grid, dan di driver jarak jauh. Hanya langkah 1 yang khusus untuk library yang ditambal.
Ringkasan
Biarkan undetected-chromedriver menangani fingerprint, dan tangani sendiri widget-nya. Tunggu [data-sitekey], pecahkan lewat localhost, tulis token ke dalam g-recaptcha-response, lalu panggil data-callback jika halaman mendeklarasikannya. Tutup driver di dalam blok finally agar binary yang ditambal tidak tertinggal.
Cakupan Selenium yang lebih luas ada di halaman pemecah CAPTCHA Selenium , daftar metode lengkapnya ada di halaman pemecah CAPTCHA Python , dan pemecahan CAPTCHA untuk web scraping membahas cara menjalankannya dalam skala besar. CapSkip adalah pemecah captcha lokal, jadi setiap pemecahan di atas terjadi di komputer Anda sendiri.
