Cara Memecahkan CAPTCHA di Tes SeleniumBase (Python)

seleniumbase captcha - How to Solve CAPTCHA in SeleniumBase Tests (Python)

SeleniumBase mengendalikan browser. Ia tidak pernah membaca CAPTCHA untuk Anda. Jadi langkah captcha di SeleniumBase terdiri dari tiga gerakan: ambil sitekey dari halaman, minta token ke solver, lalu tulis token itu kembali ke formulir dan kirim. Pemecahannya terjadi di luar browser, dan itulah sebabnya kode yang sama bekerja pada run dengan tampilan, run headless, maupun job CI. Berikut wujudnya dalam dua format sintaksis yang paling mungkin Anda pakai.

Apa yang Anda butuhkan

  • Python 3.10 atau lebih baru, dengan SeleniumBase dan SDK CapSkip sudah terinstal.
  • Halaman yang benar-benar merender widget. Kunci uji reCAPTCHA milik Google sendiri selalu lolos, jadi kunci itu tidak membuktikan apa pun tentang kode Anda.
  • CapSkip berjalan, entah dalam mode Local di alamat loopback atau dalam mode Server di mesin yang dapat dijangkau test runner Anda. Keduanya dijelaskan di pengaturan koneksi, dan pilihan mana yang Anda butuhkan bergantung pada tempat tes Anda dijalankan.
# Both packages, one command.
pip install seleniumbase capskip

Apa yang dilakukan UC mode, dan apa yang tidak

SeleniumBase menyertakan UC mode, dan ada baiknya kita tegas soal tugasnya karena banyak orang memakainya sambil mengharapkan sebuah solver. UC mode mengurangi sinyal otomatisasi yang dibocorkan browser, dan GUI helper-nya bisa mengklik kotak centang pada halaman interstitial Cloudflare. Itu masalah yang berbeda dari menghasilkan token reCAPTCHA. Tidak ada satu pun bagian UC mode yang membaca gambar terdistorsi atau memilih ubin yang berisi bus.

# pip install seleniumbase
from seleniumbase import SB

with SB(uc=True) as sb:
    # Disconnects the driver briefly so the page loads unobserved.
    sb.uc_open_with_reconnect("https://example.com/protected", reconnect_time=3)

    # Drives the real mouse pointer, so it needs a desktop session
    # or a virtual display. It clicks a checkbox; it solves nothing.
    sb.uc_gui_click_captcha()

Ada dua konsekuensinya. GUI helper membutuhkan display sungguhan, sehingga tidak bisa dipakai di sebagian besar CI headless. Dan untuk reCAPTCHA serta GeeTest Anda tetap memerlukan token, dan itulah yang dibahas sisa artikel ini. Pakai keduanya bersamaan: UC mode untuk menekan seberapa sering Anda ditantang, dan solver untuk challenge yang tetap muncul.

Langkah 1: baca sitekey dari halaman

Sitekey bersifat publik. Nilainya menempel pada elemen widget sebagai atribut, dan SeleniumBase bisa membacanya dengan satu panggilan, jadi Anda tidak perlu menuliskannya secara permanen untuk tiap lingkungan.

# pip install seleniumbase
from seleniumbase import SB

PAGE = "https://example.com/page-with-recaptcha"

with SB() as sb:
    sb.open(PAGE)

    # Present on the widget div for v2, and on the script tag for v3.
    sitekey = sb.get_attribute("[data-sitekey]", "data-sitekey")

    print(sitekey)      # this plus the page URL is all the solver needs

Langkah 2: dapatkan token dari solver

Bagian ini sama sekali tidak berkaitan dengan SeleniumBase. Ini adalah panggilan Python biasa ke layanan di komputer Anda sendiri, dan ia mengembalikan string token yang akan dihasilkan halaman itu seandainya seorang manusia melewati widget-nya.

# pip install capskip
from capskip import CapSkip

solver = CapSkip(host="127.0.0.1", port=8080)

# v2 checkbox is the default shape. Pass invisible=1 or
# enterprise=1 for those variants, or version="v3" for v3.
result = solver.recaptcha(
    sitekey=sitekey,
    url=PAGE,
)

token = result["code"]      # the value the form is waiting for

Client yang sama menangani tipe lain yang mungkin Anda temui dalam sebuah test suite. Turnstile memakai solver.turnstile dengan sitekey dan URL halaman, GeeTest memakai solver.geetest dengan nilai gt dan challenge, dan CAPTCHA gambar memakai solver.normal dengan jalur file, sebuah URL, atau data URI base64. Halaman pemecah CAPTCHA Python membahas seluruh permukaan API-nya.

Langkah 3: suntikkan token dan kirim

Google menempatkan textarea tersembunyi di dalam formulir dan mengharapkan token ada pada nilainya. Tulis ke sana dengan panggilan script, lalu kirim formulirnya seperti yang akan dilakukan UI halaman itu sendiri.

# The response field is hidden, so a normal type() will not reach it.
sb.execute_script(
    "document.getElementById('g-recaptcha-response').value = arguments[0];",
    token,
)

sb.click("button[type='submit']")
sb.assert_element(".signup-success")

Jika halaman menghubungkan fungsi callback-nya sendiri ke widget alih-alih membaca kolom saat pengiriman, panggil fungsi itu dengan token, bukan mengklik. Mana yang Anda perlukan terlihat di markup widget: atribut data-callback menyebutkan nama fungsinya, dan ketiadaannya berarti formulir membaca kolom tersebut.

Tes lengkapnya

Berikut keseluruhannya sebagai kelas BaseCase, yaitu format yang cocok dengan pytest suite yang sudah ada tanpa perkabelan tambahan.

# pip install seleniumbase capskip
from seleniumbase import BaseCase
from capskip import CapSkip

BaseCase.main(__name__, __file__)

PAGE = "https://example.com/page-with-recaptcha"


class RecaptchaTest(BaseCase):
    def test_signup_form(self):
        self.open(PAGE)
        sitekey = self.get_attribute("[data-sitekey]", "data-sitekey")

        solver = CapSkip(host="127.0.0.1", port=8080)
        token = solver.recaptcha(sitekey=sitekey, url=PAGE)["code"]

        self.execute_script(
            "document.getElementById('g-recaptcha-response').value = arguments[0];",
            token,
        )
        self.click("button[type='submit']")
        self.assert_element(".signup-success")

Pecahkan belakangan. Token reCAPTCHA hanya berlaku sekitar dua menit, jadi mengambilnya di awal tes lalu memakainya setelah empat langkah lain adalah balapan yang sesekali akan Anda kalahi. Letakkan pemecahan tepat sebelum pengiriman, dan di situ pula tempat percobaan ulang seharusnya berada.

Menjalankan solver di sebuah server

Test runner jarang berupa mesin tempat Anda duduk. CapSkip menangani itu dengan mode koneksi kedua, dan satu-satunya yang berubah di kode Anda adalah host-nya.

ModeMendengarkan diGunakan saat
Lokal127.0.0.1, hanya perangkat ituTes dan solver berjalan di satu mesin
ServerAlamat jaringan atau IP publik AndaRunner CI, sebuah VPS, atau test grid memanggil masuk
# pip install capskip
import os
from capskip import CapSkip

# The SDK reads these names from the environment too, so one test
# file runs unchanged on a laptop and on a shared runner.
solver = CapSkip(
    host=os.environ.get("CAPSKIP_HOST", "127.0.0.1"),
    port=int(os.environ.get("CAPSKIP_PORT", "8080")),
)

IP publik statis disarankan ketika pemanggilnya berada di luar jaringan Anda sendiri. Mode Server tetap perangkat keras milik Anda dan tetap tanpa kuota: yang berubah adalah tempat solver berjalan, bukan siapa pemiliknya atau berapa biayanya per pemecahan. Seluruh pilihannya ada di pengaturan koneksi.

Kesalahan umum

Apa yang Anda lihatPenyebabPerbaiki
NetworkExceptionTidak ada yang mendengarkan di host dan port tersebutJalankan CapSkip, atau arahkan host ke server yang menjalankannya
TimeoutExceptionPolling melewati recaptchaTimeoutNaikkan timeout-nya, atau pastikan sitekey yang dipakai adalah yang aktif
ERROR_GOOGLEKEYSitekey tidak pernah sampai atau formatnya salahCetak apa yang dikembalikan get_attribute sebelum Anda mengirimnya
ERROR_PAGEURLURL halaman hilang atau bukan URL lengkapKirim URL absolut yang sama dengan yang sedang dibuka browser
Formulir menolak token yang validHalaman memakai callback, bukan kolomnyaPanggil fungsi data-callback dengan token tersebut

Setiap kode yang dapat dikembalikan API tercantum di dokumentasi API CapSkip, beserta pemicu masing-masing.

FAQ

Apakah UC mode memecahkan reCAPTCHA dengan sendirinya?

Tidak. UC mode membuat browser tampak kurang otomatis dan bisa mengklik kotak centang pada interstitial Cloudflare lewat GUI helper. Keduanya sama sekali tidak menghasilkan token reCAPTCHA. Anda tetap mengambil token dari solver dan menuliskannya ke formulir, persis seperti yang ditunjukkan di atas. Jalankan keduanya: UC mode menekan seberapa sering Anda ditantang, dan solver menyelesaikan challenge yang tetap Anda terima.

Bisakah saya menjalankannya secara headless di CI?

Bisa, karena pemecahannya tidak pernah menyentuh browser. Berikan headless ke SB atau tambahkan flag-nya di baris perintah pytest, dan ketiga langkahnya tetap sama. Bagian yang tidak bertahan di runner headless adalah klik GUI milik UC mode, yang menggerakkan penunjuk mouse sungguhan dan membutuhkan sesi desktop atau display virtual.

Tes saya berjalan di runner Linux. Di mana solver-nya ditempatkan?

Di mesin Windows yang Anda kendalikan, dijangkau lewat mode Server. CapSkip adalah aplikasi Windows, jadi polanya adalah satu instance solver di mesin Windows dan sebanyak apa pun runner yang mengarah ke sana lewat API. Setel CAPSKIP_HOST di runner dan tidak ada lagi yang berubah di dalam tes.

Apakah saya perlu proxy agar pemecahannya cocok dengan browser saya?

Kadang perlu, dan hal itu didukung untuk reCAPTCHA, Turnstile, serta GeeTest. Berikan dictionary proxy berisi type dan URI, maka pemecahan dilakukan melaluinya, dan ini penting ketika situs mempermasalahkan apakah token dan sesi berasal dari alamat yang sama. CAPTCHA gambar tidak menerima proxy, karena tidak ada bagian darinya yang terikat pada jalur jaringan.

Versi singkatnya

Baca sitekey dengan get_attribute, ambil token-nya, tuliskan ke kolom respons tersembunyi, lalu kirim. Jaga agar pemecahan berada di langkah yang sama dengan pengiriman supaya token-nya masih segar, dan simpan host di variabel lingkungan supaya suite berjalan sama di mana pun. Untuk gambaran Selenium yang lebih luas, lihat halaman pemecah CAPTCHA Selenium, dan untuk hal khusus v2 lihat halaman pemecah reCAPTCHA v2. Tersisa soal biaya, dan di situlah suite yang berjalan pada setiap commit paling terasa menyakitkan: pemecah captcha lokal berarti setiap pemecahan terjadi di perangkat keras yang sudah Anda miliki, tanpa kuota, sesering apa pun tes dijalankan.