Skip to content

Instantly share code, notes, and snippets.

@anton-petrov
Created September 24, 2017 19:11
Show Gist options
  • Save anton-petrov/71906417033f821199469bdff19f1e33 to your computer and use it in GitHub Desktop.
Save anton-petrov/71906417033f821199469bdff19f1e33 to your computer and use it in GitHub Desktop.
Solve reCAPTCHA with Selenium + Python
import re, csv
from time import sleep, time
from random import uniform, randint
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException
def write_stat(loops, time):
with open('stat.csv', 'a', newline='') as csvfile:
spamwriter = csv.writer(csvfile, delimiter=',',
quotechar='"', quoting=csv.QUOTE_MINIMAL)
spamwriter.writerow([loops, time])
def check_exists_by_xpath(xpath):
try:
driver.find_element_by_xpath(xpath)
except NoSuchElementException:
return False
return True
def wait_between(a,b):
rand=uniform(a, b)
sleep(rand)
def dimention(driver):
d = int(driver.find_element_by_xpath('//div[@id="rc-imageselect-target"]/table').get_attribute("class")[-1]);
return d if d else 3 # dimention is 3 by default
# ***** main procedure to identify and submit picture solution
def solve_images(driver):
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID ,"rc-imageselect-target"))
)
dim = dimention(driver)
# ****************** check if there is a clicked tile ******************
if check_exists_by_xpath('//div[@id="rc-imageselect-target"]/table/tbody/tr/td[@class="rc-imageselect-tileselected"]'):
rand2 = 0
else:
rand2 = 1
# wait before click on tiles
wait_between(0.5, 1.0)
# ****************** click on a tile ******************
tile1 = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH , '//div[@id="rc-imageselect-target"]/table/tbody/tr[{0}]/td[{1}]'.format(randint(1, dim), randint(1, dim ))))
)
tile1.click()
if (rand2):
try:
driver.find_element_by_xpath('//div[@id="rc-imageselect-target"]/table/tbody/tr[{0}]/td[{1}]'.format(randint(1, dim), randint(1, dim))).click()
except NoSuchElementException:
print('\n\r No Such Element Exception for finding 2nd tile')
#****************** click on submit buttion ******************
driver.find_element_by_id("recaptcha-verify-button").click()
start = time()
url='...'
driver = webdriver.Firefox()
driver.get(url)
mainWin = driver.current_window_handle
# move the driver to the first iFrame
driver.switch_to_frame(driver.find_elements_by_tag_name("iframe")[0])
# ************* locate CheckBox **************
CheckBox = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID ,"recaptcha-anchor"))
)
# ************* click CheckBox ***************
wait_between(0.5, 0.7)
# making click on captcha CheckBox
CheckBox.click()
#***************** back to main window **************************************
driver.switch_to_window(mainWin)
wait_between(2.0, 2.5)
# ************ switch to the second iframe by tag name ******************
driver.switch_to_frame(driver.find_elements_by_tag_name("iframe")[1])
i=1
while i<130:
print('\n\r{0}-th loop'.format(i))
# ******** check if checkbox is checked at the 1st frame ***********
driver.switch_to_window(mainWin)
WebDriverWait(driver, 10).until(
EC.frame_to_be_available_and_switch_to_it((By.TAG_NAME , 'iframe'))
)
wait_between(1.0, 2.0)
if check_exists_by_xpath('//span[@aria-checked="true"]'):
import winsound
winsound.Beep(400,1500)
write_stat(i, round(time()-start) - 1 ) # saving results into stat file
break
driver.switch_to_window(mainWin)
# ********** To the second frame to solve pictures *************
wait_between(0.3, 1.5)
driver.switch_to_frame(driver.find_elements_by_tag_name("iframe")[1])
solve_images(driver)
i=i+1
@PhilipCNel
Copy link

Good work!

Is windows beep necessary and why are you using break in line 101?

@PhilipCNel
Copy link

And how will your solve_images be successful if it only selectes random tiles? Or can you determine the success tiles via their xpath?

@magyargergo
Copy link

magyargergo commented Jan 23, 2022

I updated this script:

import csv
from time import sleep, time
from random import uniform, randint
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
from selenium.common.exceptions import NoSuchElementException


def write_stat(loops, _time):
    with open("stat.csv", "a", newline="") as csvfile:
        spam_writer = csv.writer(
            csvfile, delimiter=",", quotechar='"', quoting=csv.QUOTE_MINIMAL
        )
        spam_writer.writerow([loops, _time])


def check_exists_by_xpath(driver, xpath):
    try:
        driver.find_element_by_xpath(xpath)
    except NoSuchElementException:
        return False
    return True


def wait_between(a, b):
    rand = uniform(a, b)
    sleep(rand)


def dimention(driver):
    d = int(
        driver.find_element_by_xpath(
            '//div[@id="rc-imageselect-target"]/table'
        ).get_attribute("class")[-1]
    )
    return d if d else 3  # dimention is 3 by default


# ***** main procedure to identify and submit picture solution
def solve_images(driver):
    WebDriverWait(driver, 10).until(
        ec.presence_of_element_located((By.ID, "rc-imageselect-target"))
    )
    dim = dimention(driver)
    # ****************** check if there is a clicked tile ******************
    if check_exists_by_xpath(
        driver,
        '//div[@id="rc-imageselect-target"]/table/tbody/tr/td[@class="rc-imageselect-tileselected"]',
    ):
        rand2 = 0
    else:
        rand2 = 1

    # wait before click on tiles
    wait_between(0.5, 1.0)
    # ****************** click on a tile ******************
    tile1 = WebDriverWait(driver, 10).until(
        ec.element_to_be_clickable(
            (
                By.XPATH,
                '//div[@id="rc-imageselect-target"]/table/tbody/tr[{0}]/td[{1}]'.format(
                    randint(1, dim), randint(1, dim)
                ),
            )
        )
    )
    tile1.click()
    if rand2:
        try:
            driver.find_element_by_xpath(
                '//div[@id="rc-imageselect-target"]/table/tbody/tr[{0}]/td[{1}]'.format(
                    randint(1, dim), randint(1, dim)
                )
            ).click()
        except NoSuchElementException:
            print("\n\r No Such Element Exception for finding 2nd tile")

    # ****************** click on submit buttion ******************
    driver.find_element_by_id("recaptcha-verify-button").click()


start = time()


def resolve(driver):
    main_win = driver.current_window_handle

    driver.switch_to.default_content()

    # *************  locate first iframe  **************
    iframe1 = WebDriverWait(driver, 0.5).until(
        ec.presence_of_element_located((By.ID, "main-iframe"))
    )

    # move the driver to the first iFrame
    driver.switch_to.frame(iframe1)

    # *************  locate second iframe  **************
    iframe2 = WebDriverWait(driver, 0.5).until(
        ec.presence_of_element_located(
            (
                By.CSS_SELECTOR,
                "iframe[name*='a-'][src*='https://www.google.com/recaptcha/api2/anchor?']",
            )
        )
    )

    # move the driver to the second iFrame
    driver.switch_to.frame(iframe2)

    # *************  locate CheckBox  **************
    check_box = WebDriverWait(driver, 10).until(
        ec.presence_of_element_located((By.ID, "recaptcha-anchor"))
    )

    # *************  click CheckBox  ***************
    wait_between(0.5, 0.7)
    # making click on captcha CheckBox
    check_box.click()

    # ***************** back to main window **************************************
    driver.switch_to.window(main_win)

    wait_between(2.0, 2.5)

    # move the driver to the first iFrame
    driver.switch_to.frame(iframe1)

    # *************  locate the popup's iframe  **************
    iframe_popup = WebDriverWait(driver, 0.5).until(
        ec.presence_of_element_located(
            (
                By.CSS_SELECTOR,
                 "iframe[title*='recaptcha challenge'][src*='https://www.google.com/recaptcha/api2/bframe?']",
            )
        )
    )

    i = 1
    while i < 130:
        print("\n\r{0}-th loop".format(i))
        # ******** check if checkbox is checked at the 1st frame ***********
        driver.switch_to.window(main_win)
        WebDriverWait(driver, 10).until(
            ec.frame_to_be_available_and_switch_to_it((By.TAG_NAME, "iframe"))
        )
        wait_between(1.0, 2.0)
        if check_exists_by_xpath(driver, '//span[@aria-checked="true"]'):
            write_stat(i, round(time() - start) - 1)  # saving results into stat file
            break

        driver.switch_to.window(main_win)

        wait_between(0.3, 1.5)

        # move the driver to the first iFrame
        driver.switch_to.frame(iframe1)

        # ********** To the second frame to solve pictures *************
        driver.switch_to.frame(iframe_popup)
        solve_images(driver)
        i = i + 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment