このチュートリアルでは、Selenium 4 で Google の reCAPTCHA デモページを開き、実際のブラウザ上で画像問題を解きます。問題文と画像を読み取り、reCAPTCHA v2 画像認識(ReCaptchaV2Classification)でクリックすべきマスを判定し、クリックを再現します。token を取得する方式と異なり、ブラウザ内で実際に検証を完了するため、token の通過率が低いサイトに適しています。
コードを書きたくない場合は、同じ API を使って自動クリックする ブラウザ拡張機能 をそのままご利用ください。
pip install requests selenium pillowexport YESCAPTCHA_CLIENT_KEY=你的clientKeyChrome のインストールが必要です。Selenium 4 は、バージョンが一致する chromedriver を自動でダウンロードします。
- チェックボックスをクリックする。 チェックボックスは
title="reCAPTCHA"の iframe 内にあります。iframe に切り替えて#recaptcha-anchorをクリックします。 - 問題の iframe に切り替える。 問題は別の iframe(title に “challenge” を含む)内にあります。
- 問題文を読み取る。
.rc-imageselect-desc-wrapper strong内の太字が探す対象です(例: “traffic lights”)。API が必要とするのは問題 ID なので、対応表で名称を ID(/m/015qff)に変換します。問題 ID を参照してください。ブラウザの表示言語を英語にすると照合しやすくなります。 - 画像を取得する。 各マスの画像は実際には 1 枚の大きな画像です。
td.rc-imageselect-tile imgのsrcをダウンロードします。9 マス(3x3)は 300×300、16 マス(4x4)は 450×450 にリサイズし、Base64 に変換します。 - 認識する。 タイプ
ReCaptchaV2ClassificationでcreateTaskを呼び出し、imageとquestionを渡します。"confidence": 0.5を加えると、3x3 の画像では該当するマスがすべて一度に返されるため、クリック後に更新される小さな画像を処理する必要がなくなります。 - クリックする。 返された
objectsはマスの番号で、0 から始まり、左から右、上から下の順です。対応するtdを順にクリックします。 - 検証する。
#recaptcha-verify-buttonをクリックします。新しい問題が表示された場合は手順 3 に戻ります。問題のウィンドウが閉じれば通過です。 - フォームを送信する。 メインページに戻り、送信ボタンをクリックします。
完全なコード
Section titled “完全なコード”"""Click through a reCAPTCHA v2 image challenge with Selenium 4 and ReCaptchaV2Classification.
Flow: open the page -> click the checkbox -> read the target name and the grid image ->ask YesCaptcha which tiles to click -> click them -> press Verify. Repeat if a new challenge appears.
Run: pip install requests selenium pillow export YESCAPTCHA_CLIENT_KEY=your_client_key python recaptcha_click_selenium.pyEach recognized image is charged (see the price list). reCAPTCHA's page structure can change;adjust the selectors below if a step stops working."""import base64import ioimport osimport time
import requestsfrom PIL import Imagefrom selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.support.wait import WebDriverWait
CLIENT_KEY = os.environ["YESCAPTCHA_CLIENT_KEY"]PAGE_URL = "https://www.google.com/recaptcha/api2/demo"
# Target names shown in the challenge (English UI) -> question IDs.# Full list: https://docs.yescaptcha.com/en/tasks/recaptcha-classification/QUESTION_IDS = { "taxis": "/m/0pg52", "bus": "/m/01bjv", "buses": "/m/01bjv", "motorcycles": "/m/04_sv", "tractors": "/m/013xlm", "chimneys": "/m/01jk_4", "crosswalks": "/m/014xcs", "traffic lights": "/m/015qff", "bicycles": "/m/0199g", "parking meters": "/m/015qbp", "cars": "/m/0k4j", "bridges": "/m/015kr", "boats": "/m/019jd", "palm trees": "/m/0cdl1", "mountains or hills": "/m/09d_r", "fire hydrants": "/m/01pns0", "a fire hydrant": "/m/01pns0", "stairs": "/m/01lynh",}
def classify(image_b64, question): task = {"type": "ReCaptchaV2Classification", "image": image_b64, "question": question, "confidence": 0.5} data = requests.post( "https://api.yescaptcha.com/createTask", json={"clientKey": CLIENT_KEY, "task": task}, timeout=30, ).json() if data.get("errorId"): raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}") return data["solution"] # synchronous: the solution comes back right away
def grid_image_b64(url, size): """Download the challenge image and scale it to the standard size (300 for 3x3, 450 for 4x4).""" img = Image.open(io.BytesIO(requests.get(url, timeout=30).content)).convert("RGB") img = img.resize((size, size)) buf = io.BytesIO() img.save(buf, format="JPEG") return base64.b64encode(buf.getvalue()).decode()
driver = webdriver.Chrome()wait = WebDriverWait(driver, 15)try: driver.get(PAGE_URL)
# 1. Click the checkbox (inside the "reCAPTCHA" iframe) wait.until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, 'iframe[title="reCAPTCHA"]'))) wait.until(EC.element_to_be_clickable((By.ID, "recaptcha-anchor"))).click() driver.switch_to.default_content()
# 2. Switch to the challenge iframe and solve rounds until it closes wait.until(EC.frame_to_be_available_and_switch_to_it( (By.XPATH, '//iframe[contains(@title, "challenge")]'))) for _ in range(5): target = wait.until(EC.presence_of_element_located( (By.CSS_SELECTOR, ".rc-imageselect-desc-wrapper strong"))).text.strip().lower() question = QUESTION_IDS.get(target) if not question: print("unsupported target, reloading:", target) driver.find_element(By.ID, "recaptcha-reload-button").click() time.sleep(2) continue tiles = driver.find_elements(By.CSS_SELECTOR, "td.rc-imageselect-tile") size = 450 if len(tiles) == 16 else 300 url = driver.find_element(By.CSS_SELECTOR, "td.rc-imageselect-tile img").get_attribute("src") solution = classify(grid_image_b64(url, size), question) for index in solution.get("objects", []): tiles[index].click() time.sleep(0.3) time.sleep(1) driver.find_element(By.ID, "recaptcha-verify-button").click() time.sleep(3) driver.switch_to.default_content() frame = driver.find_element(By.XPATH, '//iframe[contains(@title, "challenge")]') if not frame.is_displayed(): # challenge closed: passed break driver.switch_to.frame(frame)
driver.switch_to.default_content() driver.find_element(By.ID, "recaptcha-demo-submit").click() time.sleep(2) print("passed" if "Verification Success" in driver.page_source else "not passed")finally: driver.quit()- reCAPTCHA のページ構造は更新されます。コード内のセレクタが機能しなくなった場合は、実際のページに合わせて調整してください。
- 画像 1 枚を認識するたびに課金されます(料金は reCAPTCHA v2 画像認識 を参照)。クリック後に検証に失敗したタスクは、1 時間以内に 報告 すると、報告による返金を申請できます。
- 対応表にない問題が出た場合は、更新ボタンを押して別の問題に切り替えるか、サポートに連絡して対応を追加してもらってください。
© YesCaptcha