-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathRecaptchaSolver.py
139 lines (113 loc) · 5.71 KB
/
RecaptchaSolver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import os
import random
import asyncio
import aiohttp
import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
from pydub import AudioSegment
import speech_recognition as sr
class RecaptchaSolver:
def __init__(self, driver):
self.driver = driver
async def download_audio(self, url, path):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
with open(path, 'wb') as f:
f.write(await response.read())
print("Downloaded audio asynchronously.")
def solveCaptcha(self):
try:
# Switch to the CAPTCHA iframe
iframe_inner = WebDriverWait(self.driver, 10).until(
EC.frame_to_be_available_and_switch_to_it((By.XPATH, "//iframe[contains(@title, 'reCAPTCHA')]"))
)
# Click on the CAPTCHA box
WebDriverWait(self.driver, 10).until(
EC.element_to_be_clickable((By.ID, 'recaptcha-anchor'))
).click()
# Check if the CAPTCHA is solved
time.sleep(1) # Allow some time for the state to update
if self.isSolved():
print("CAPTCHA solved by clicking.")
self.driver.switch_to.default_content() # Switch back to main content
return
# If not solved, attempt audio CAPTCHA solving
self.solveAudioCaptcha()
except Exception as e:
print(f"An error occurred while solving CAPTCHA: {e}")
self.driver.switch_to.default_content() # Ensure we switch back in case of error
raise
def solveAudioCaptcha(self):
try:
self.driver.switch_to.default_content()
# Switch to the audio CAPTCHA iframe
iframe_audio = WebDriverWait(self.driver, 10).until(
EC.frame_to_be_available_and_switch_to_it((By.XPATH, '//iframe[@title="recaptcha challenge expires in two minutes"]'))
)
# Click on the audio button
audio_button = WebDriverWait(self.driver, 10).until(
EC.element_to_be_clickable((By.ID, 'recaptcha-audio-button'))
)
audio_button.click()
# Get the audio source URL
audio_source = WebDriverWait(self.driver, 10).until(
EC.presence_of_element_located((By.ID, 'audio-source'))
).get_attribute('src')
print(f"Audio source URL: {audio_source}")
# Download the audio to the temp folder asynchronously
temp_dir = os.getenv("TEMP") if os.name == "nt" else "/tmp/"
path_to_mp3 = os.path.normpath(os.path.join(temp_dir, f"{random.randrange(1, 1000)}.mp3"))
path_to_wav = os.path.normpath(os.path.join(temp_dir, f"{random.randrange(1, 1000)}.wav"))
asyncio.run(self.download_audio(audio_source, path_to_mp3))
# Convert mp3 to wav
sound = AudioSegment.from_mp3(path_to_mp3)
sound.export(path_to_wav, format="wav")
print("Converted MP3 to WAV.")
# Recognize the audio
recognizer = sr.Recognizer()
with sr.AudioFile(path_to_wav) as source:
audio = recognizer.record(source)
captcha_text = recognizer.recognize_google(audio).lower()
print(f"Recognized CAPTCHA text: {captcha_text}")
# Enter the CAPTCHA text
audio_response = WebDriverWait(self.driver, 20).until(
EC.presence_of_element_located((By.ID, 'audio-response'))
)
audio_response.send_keys(captcha_text)
audio_response.send_keys(Keys.ENTER)
print("Entered and submitted CAPTCHA text.")
# Wait for CAPTCHA to be processed
time.sleep(0.8) # Increase this if necessary
# Verify CAPTCHA is solved
if self.isSolved():
print("Audio CAPTCHA solved.")
else:
print("Failed to solve audio CAPTCHA.")
raise Exception("Failed to solve CAPTCHA")
except Exception as e:
print(f"An error occurred while solving audio CAPTCHA: {e}")
self.driver.switch_to.default_content() # Ensure we switch back in case of error
raise
finally:
# Always switch back to the main content
self.driver.switch_to.default_content()
def isSolved(self):
try:
# Switch back to the default content
self.driver.switch_to.default_content()
# Switch to the reCAPTCHA iframe
iframe_check = self.driver.find_element(By.XPATH, "//iframe[contains(@title, 'reCAPTCHA')]")
self.driver.switch_to.frame(iframe_check)
# Find the checkbox element and check its aria-checked attribute
checkbox = WebDriverWait(self.driver, 10).until(
EC.presence_of_element_located((By.ID, 'recaptcha-anchor'))
)
aria_checked = checkbox.get_attribute("aria-checked")
# Return True if the aria-checked attribute is "true" or the checkbox has the 'recaptcha-checkbox-checked' class
return aria_checked == "true" or 'recaptcha-checkbox-checked' in checkbox.get_attribute("class")
except Exception as e:
print(f"An error occurred while checking if CAPTCHA is solved: {e}")
return False