Otomatiskan pengiriman formulir yang menyertakan tantangan CAPTCHA menggunakan Selenium dan CaptchaAI.
Tantangannya
Formulir web dilindungi oleh otomatisasi blok CAPTCHA. Baik Anda menguji formulir kontak, mengirimkan aplikasi, atau menjalankan alur kerja QA, Anda perlu menyelesaikan CAPTCHA sebelum formulir menerima kiriman Anda.
Arsitektur
┌────────────┐ ┌──────────────┐ ┌────────────┐ ┌──────────────┐
│ Load Form │────▶│ Fill Fields │────▶│ Detect & │────▶│ Submit Form │
│ (Selenium) │ │ │ │ Solve │ │ │
│ │ │ │ │ CAPTCHA │ │ │
└────────────┘ └──────────────┘ └────────────┘ └──────────────┘
Komponen Inti
Pemecah CAPTCHA
import time
import requests
class FormCaptchaSolver:
BASE = "https://ocr.captchaai.com"
def __init__(self, api_key):
self.api_key = api_key
def solve(self, params, initial_wait=10):
params["key"] = self.api_key
params["json"] = 1
resp = requests.post(f"{self.BASE}/in.php", data=params).json()
if resp["status"] != 1:
raise Exception(f"Submit error: {resp['request']}")
task_id = resp["request"]
time.sleep(initial_wait)
for _ in range(60):
result = requests.get(
f"{self.BASE}/res.php",
params={"key": self.api_key, "action": "get", "id": task_id, "json": 1},
).json()
if result["request"] == "CAPCHA_NOT_READY":
time.sleep(5)
continue
if result["status"] == 1:
return result["request"]
raise Exception(f"Solve error: {result['request']}")
raise TimeoutError("CAPTCHA solve timed out")
Detektor CAPTCHA
import re
from selenium.webdriver.common.by import By
class CaptchaDetector:
def __init__(self, driver):
self.driver = driver
def detect(self):
"""Detect CAPTCHA type on current page."""
html = self.driver.page_source
# Turnstile
turnstile = self.driver.find_elements(By.CSS_SELECTOR, ".cf-turnstile, [data-sitekey]")
for el in turnstile:
if "cf-turnstile" in (el.get_attribute("class") or ""):
return "turnstile", el.get_attribute("data-sitekey")
# reCAPTCHA
recaptcha = self.driver.find_elements(By.CSS_SELECTOR, "[data-sitekey]")
if recaptcha:
sitekey = recaptcha[0].get_attribute("data-sitekey")
if "recaptcha" in html.lower():
return "recaptcha_v2", sitekey
# Image CAPTCHA
img = self.driver.find_elements(By.CSS_SELECTOR, "img[src*='captcha'], img.captcha")
if img:
return "image", img[0].get_attribute("src")
return "none", None
Pengotomasi Formulir
import base64
import requests as req
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class FormAutomator:
def __init__(self, api_key):
self.solver = FormCaptchaSolver(api_key)
self.driver = webdriver.Chrome()
self.detector = CaptchaDetector(self.driver)
def fill_field(self, selector, value):
field = WebDriverWait(self.driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, selector))
)
field.clear()
field.send_keys(value)
def select_option(self, selector, value):
from selenium.webdriver.support.ui import Select
select = Select(self.driver.find_element(By.CSS_SELECTOR, selector))
select.select_by_value(value)
def solve_captcha(self):
captcha_type, data = self.detector.detect()
page_url = self.driver.current_url
if captcha_type == "recaptcha_v2":
token = self.solver.solve({
"method": "userrecaptcha",
"googlekey": data,
"pageurl": page_url,
})
self.driver.execute_script(
f'document.querySelector("[name=g-recaptcha-response]").value = "{token}";'
)
return True
if captcha_type == "turnstile":
token = self.solver.solve({
"method": "turnstile",
"sitekey": data,
"pageurl": page_url,
})
self.driver.execute_script(
f'document.querySelector("[name=cf-turnstile-response]").value = "{token}";'
)
return True
if captcha_type == "image":
img_data = req.get(data).content
img_b64 = base64.b64encode(img_data).decode()
text = self.solver.solve({"method": "base64", "body": img_b64})
captcha_input = self.driver.find_element(
By.CSS_SELECTOR, "input[name*='captcha']"
)
captcha_input.clear()
captcha_input.send_keys(text)
return True
return False # No CAPTCHA detected
def submit_form(self, url, fields, submit_selector="button[type='submit']"):
"""
fields: list of (selector, value) tuples
"""
self.driver.get(url)
for selector, value in fields:
self.fill_field(selector, value)
self.solve_captcha()
submit = self.driver.find_element(By.CSS_SELECTOR, submit_selector)
submit.click()
return self.driver.current_url
def close(self):
self.driver.quit()
Contoh Lengkap: Formulir Kontak
automator = FormAutomator("YOUR_API_KEY")
try:
result_url = automator.submit_form(
url="https://example.com/contact",
fields=[
("#name", "John Doe"),
("#email", "john@example.com"),
("#subject", "Sales inquiry"),
("#message", "I'd like to learn more about your services."),
],
submit_selector="#submit-btn",
)
print(f"Form submitted. Redirected to: {result_url}")
finally:
automator.close()
Menangani Berbagai Jenis Formulir
Formulir Masuk
result = automator.submit_form(
url="https://staging.example.com/qa-login",
fields=[
("#username", "testuser"),
("#password", "testpass123"),
],
submit_selector="#login-btn",
)
Formulir Pendaftaran
result = automator.submit_form(
url="https://example.com/register",
fields=[
("#first-name", "Jane"),
("#last-name", "Smith"),
("#email", "jane@example.com"),
("#password", "SecurePass!123"),
("#confirm-password", "SecurePass!123"),
],
submit_selector="#register-btn",
)
Formulir Pencarian dengan CAPTCHA
result = automator.submit_form(
url="https://example.com/search",
fields=[
("#query", "python developer"),
("#location", "San Francisco"),
],
submit_selector="#search-btn",
)
Pemecahan Masalah
| Masalah | Penyebab | Solusi |
|---|---|---|
| Token ditolak | Token kedaluwarsa sebelum diserahkan | Selesaikan CAPTCHA terakhir, segera kirimkan |
| Bidang tidak ditemukan | Pemuatan halaman dinamis | Tambahkan waktu tunggu yang eksplisit |
| Jenis CAPTCHA yang salah terdeteksi | Beberapa elemen CAPTCHA | Periksa urutan deteksi |
| Formulir dimuat ulang setelah dikirimkan | Validasi sisi server gagal | Periksa semua bidang yang wajib diisi |
| Callback reCAPTCHA tidak terpicu | Perlu memanggil fungsi callback | Gunakan grecaptcha.execute() setelah injeksi |
Pertanyaan Umum
Bisakah saya mengirimkan formulir tanpa browser?
Untuk reCAPTCHA dan Turnstile, Anda dapat menyelesaikan CAPTCHA tanpa browser dan mengirimkannya melalui HTTP POST. Namun jika form menggunakan validasi JavaScript, diperlukan browser.
Bagaimana cara menangani formulir dengan banyak CAPTCHA?
Beberapa formulir memperlihatkan CAPTCHA hanya setelah validasi gagal. Jalankan solve_captcha() lagi setelah setiap upaya pengiriman.
Bagaimana dengan formulir AJAX?
Untuk pengiriman AJAX, intersepsi permintaan XHR dan sertakan token CAPTCHA dalam payload permintaan alih-alih mengisi kolom tersembunyi.
Panduan Terkait
- Cara Mengatasi reCAPTCHA v2 Menggunakan API
- Cara Mengatasi Cloudflare Turnstile Menggunakan API
Otomatiskan formulir apa pun – selesaikan CAPTCHA dengan CaptchaAI.