2captcha API + selenium - python

So i'm using this 2captcha API and testing it on a site like omegle.com.
The captcha solving happens but the google captcha box doesnt get ticked and nothing happens. Wondering why that is, I know the 2captcha API runs perfectly... but does it only work for HTTP requests and not selenium?
Here is the API link i inserted into the code below:
https://github.com/2captcha/2captcha-api-examples/blob/master/ReCaptcha%20v2%20API%20Examples/Python%20Example/2captcha_python_api_example.py
from selenium import webdriver
from time import sleep
from selenium.common.exceptions import InvalidElementStateException
from selenium.common.exceptions import UnexpectedAlertPresentException
import time,os
import requests
fp = webdriver.FirefoxProfile('C:\\Users\\mo\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\b0wnbtro.dev-edition-default')
interest = input("Enter the interests seperate by a comma ")
msg1 = "1"
msg2 ="2"
msg3 = "3"
msg4 = "4"
driver = webdriver.Firefox(fp)
#2CAPTCHA API CODE INSERTED HERE FOR A TEST RUN BEFORE BEING INCORPORATED IN A LOOP
def main():
try:
driver.get('http://www.omegle.com')
time.sleep(1)
#driver.find_elements_by_xpath("//*[contains(text(), 'I'm not a robot')]")
#send.click()
driver.find_element_by_xpath('//textarea[#rows="3"]').clear()
message = driver.find_element_by_xpath('//textarea[#rows="3"]')
time.sleep(3)
message.send_keys(msg1)
send = driver.find_element_by_xpath('//button[#class="sendbtn"]')
send.click()
time.sleep(6)
message.send_keys(msg2)
send = driver.find_element_by_xpath('//button[#class="sendbtn"]')
send.click()
time.sleep(10)
message.send_keys(msg3)
send = driver.find_element_by_xpath('//button[#class="sendbtn"]')
send.click()
time.sleep(25)
message.send_keys(msg4)
send = driver.find_element_by_xpath('//button[#class="sendbtn"]')
send.click()
disconnect = driver.find_element_by_xpath('//button[#class="disconnectbtn"]')
disconnect.click()
disconnect = driver.find_element_by_xpath('//button[#class="disconnectbtn"]')
disconnect.click()
disconnect = driver.find_element_by_xpath('//button[#class="disconnectbtn"]')
disconnect.click()
except (InvalidElementStateException, UnexpectedAlertPresentException):
main2()
def main2():
try:
driver.get('http://www.omegle.com')
interest1 = driver.find_element_by_xpath('//input[#class="newtopicinput"]')
interest1.send_keys(interest)
btn = driver.find_element_by_id("textbtn")
btn.click()
time.sleep(5)
driver.find_element_by_xpath('//textarea[#rows="3"]').clear()
message = driver.find_element_by_xpath('//textarea[#rows="3"]')
time.sleep(1)
time.sleep(2)
message.send_keys(msg1)
send = driver.find_element_by_xpath('//button[#class="sendbtn"]')
send.click()
time.sleep(6)
message.send_keys(msg2)
send.click()
time.sleep(10)
message.send_keys(msg3)
send.click()
time.sleep(25)
message.send_keys(msg4)
send.click()
send.click()
disconnect = driver.find_element_by_xpath('//button[#class="disconnectbtn"]')
disconnect.click()
except (InvalidElementStateException,UnexpectedAlertPresentException) :
disconnect = driver.find_element_by_xpath('//button[#class="disconnectbtn"]')
disconnect.click()
else:
main2()
while True:
try:
main2()
except (InvalidElementStateException,UnexpectedAlertPresentException) :
main()

I hope you already found a solution, but want to leave a comment for those who can get stuck at the same point.
The API does work for Selenium too.
The checkbox will not be ticked, it is controlled by ReCaptcha javascript and you do not touch it.
All you need to do is to place the token into g-recaptcha-response field. With Selenium you can do that executing JavaScript
document.querySelector('#g-recaptcha-response').textContent='token_string'
And in your case as there's nothing that submits the form you have to execute the callback function that is JavaScript too. For example:
___grecaptcha_cfg.clients[0].NY.N.callback('token_string')
The path of callback function changes so you need to find a valid one exploring ___grecaptcha_cfg object.

Related

Open whatsapp on a headless browser

Use case:
Sending out automated WhatsApp messages using pythonanywhere. Step by step logic below:
non-coders write on a gsheet the phone numbers to which we should
send out the messages
the gsheet data is read (using gspread in pythonanywhere)
open WhatsApp URL to send out the messages in bulk
I have a code using selenium running on my machine that opens the web whatsapp url, finds the needed elements on the website, and sends the messages to the gsheets phone numbers - find below a snippet from that part of the code that I am using on my machine:
global driver
driver.get('https://web.whatsapp.com/')
waiter.until(EC.title_is("WhatsApp"))
waitCounter = 0
while 1:
try:
waiter.until(EC.presence_of_element_located((By.XPATH, "//canvas[#aria-label='Scan me!']")))
waitCounter+=1
if waitCounter%1000 == 0:
print("Waiting for user to log in...", 'WARNING')
except:
print("Logged in to WhatsApp")
break
for entry in data:
driver.find_element_by_xpath(PHONE_NUMER_INPUT).send_keys(str(entry['PhoneNumber']))
time.sleep(2)
driver.find_element_by_xpath(PHONE_NUMER_INPUT).send_keys(Keys.ENTER)
time.sleep(2)
driver.find_element_by_class_name('p3_M1').send_keys(str(entry['Message']))
time.sleep(2)
driver.find_element_by_class_name('_4sWnG').click()
time.sleep(2)
Doubt:
To make step nr 3. working on python anywhere I would have to use a headless browser. However, to initiate whatsapp web we always need to do the QR code scan, so I am not being able to do it that way. Find below the current (useless) part of my code with the headless selenium code - (NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":"//*[#id='side']/div[1]/div/label/div/div[2]"}). I am quite stuck here. Any tip or idea to overcome this is more than welcome and happy to discuss any possible solutions using other libraries that you guys might find appropriate.
Thanks in advance.
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--disable-gpu")
driver = webdriver.Chrome(options=chrome_options)
def send_whatsapp_message():
global driver
driver.get('https://web.whatsapp.com/')
print("Done updating, check the spreadsheet now")
#redirect('https://web.whatsapp.com/', code=302)
for entry in data:
driver.find_element_by_xpath("//*[#id='side']/div[1]/div/label/div/div[2]").send_keys(str(entry['PhoneNumber']))
time.sleep(2)
driver.find_element_by_xpath("//*[#id='side']/div[1]/div/label/div/div[2]").send_keys(Keys.ENTER)
time.sleep(2)
driver.find_element_by_class_name('p3_M1').send_keys(str(entry['Message']))
time.sleep(2)
driver.find_element_by_class_name('_4sWnG').click()
time.sleep(2)
print("Successfully send message to {0}, name: {1}".format(str(entry['PhoneNumber']), str(entry['Name'])), 'INFO')

How to get text of an element that keeps changing in python

I am just trying to automate a website like Replika (the chatbot). In it, a new chat always keeps coming but with a whole new xpath and id. It's getting difficult for me to track the recent chat with selenium. I did try the solutions listed here and here, but they didn't work for me (or maybe I did something wrong with it). I have just started to use selenium so I don't know a lot of things about it. Please help me out. I am using python 3.8.2.
Here is the code:
from selenium import webdriver
import time
from selenium.webdriver.common.keys import Keys
from bs4 import BeautifulSoup
from urllib.request import urlopen
browser = webdriver.Chrome("C:\Chromedriver\chromedriver.exe")
browser.get("https://my.replika.ai/")
time.sleep(3)
browser.find_element_by_xpath("""//*
[#id="root"]/div/div[1]/main/a[2]""").click()
time.sleep(2)
### Login ###
browser.find_element_by_xpath("""//*
[#id="emailOrPhone"]""").send_keys("gmail_id")
time.sleep(1)
browser.find_element_by_xpath("""//*[#id="loginForm"]/button""").click()
time.sleep(3)
### Password ###
browser.find_element_by_xpath("""//*[#id="login-
password"]""").send_keys("gmail_password")
time.sleep(1)
browser.find_element_by_xpath("""//*[#id="loginForm"]/button""").click()
time.sleep(10)
### Accept the cookies ###
browser.find_element_by_xpath("""//*
[#id="root"]/div/div[1]/div[1]/button""").click()
time.sleep(5)
### Getting the Latest text ### Here is where it doesn't work
# This is a implementation that I tried and it didn't work
url = "https://my.replika.ai/"
# We use try-except in case the request was unsuccessful because of
# wrong URL
try:
page = urlopen(url)
except Exception:
print("Error opening the URL")
soup = BeautifulSoup(page, 'html.parser')
content = soup.find('div', {"id": "chat-messages"})
chat = ''
for i in content.findAll('span'):
chat = chat + ' ' + i.text
print(chat)
Thanks in Advance.
browser = webdriver.Chrome()
browser.get("https://my.replika.ai/")
time.sleep(3)
browser.find_element_by_xpath("""//*
[#id="root"]/div/div[1]/main/a[2]""").click()
time.sleep(2)
### Login ###
browser.find_element_by_xpath("""//*
[#id="emailOrPhone"]""").send_keys("username")
time.sleep(1)
browser.find_element_by_xpath("""//*[#id="loginForm"]/button""").click()
time.sleep(5)
### Password ###
browser.find_element_by_xpath("""//*[#id="login-password"]""").send_keys("password")
time.sleep(1)
browser.find_element_by_xpath("""//*[#id="loginForm"]/button""").click()
time.sleep(3)
### Accept the cookies ###
browser.find_element_by_xpath("""//*
[#id="root"]/div/div[1]/div[1]/button""").click()
time.sleep(5)
a = browser.find_elements(By.XPATH, "//*[#data-author]")
print([i.text for i in a])
print("last text : " + a[-1].text)
just use the locator
browser.find_elements(By.XPATH, "//*[#data-author]")
this finds all the elements that has the attribute #data-author (only chat has this property) and access a[-1] to get the last element . call a[-1].text to get text from it

twitter bot selenium not liking all tweets on the page

I'm learning about selenium on python and came across an error I don`t really know how to solve:
In this project the bot I've designed was supossed to Like all the tweets on the page when I searched for a certain subject. Altought the bot go through all the loops and like half of the tweets, it still misses every 2 or 3 tweets. Could somebody shed a light on why is it missing tweets?
# it's essencial that the user first pip install selenium on his system or on the source code editor such as visual code
# afterwards download the latest geckodriver on github and unzip it on the root of your python folder
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
class TwitterBot:
def __init__(self,username,password):
self.username = username
self.password = password
self.bot = webdriver.Firefox()
def login(self):
bot = self.bot
bot.get('https://twitter.com/login')
time.sleep(5) # I used a timer to load wait for the page to load before entering the login and password
email = bot.find_element_by_name("session[username_or_email]")
password = bot.find_element_by_name("session[password]")
email.clear()
password.clear()
email.send_keys(self.username)
password.send_keys(self.password)
password.send_keys(Keys.RETURN)
time.sleep(5)
def like_tweet(self,hashtag):
bot = self.bot
bot.get('https://twitter.com/search?q='+hashtag+'&src=typeahead_click')
time.sleep(3)
bot.find_element_by_link_text("Latest").click()
time.sleep(3)
for i in range(6):
bot.execute_script('window.scrollTo(0,document.body.scrollHeight)')
time.sleep(3)
tweets = bot.find_elements_by_xpath('//div[#data-testid="tweet"]')
for tweet in tweets:
try:
bot.find_element_by_xpath('//div[#data-testid="like"]').click()
time.sleep(3)
except:
print("ERROR")
bot = TwitterBot('xxx#gmail.com','xxxxx') # Enter here your username/e-mail and password like this: ('email#email.com','password')
bot.login()
bot.like_tweet('python learning') # Enter here the subject you want the bot to search for ('subject')

Selenium submit button element not interactable

I posted recently about some trouble I was having with selenium, primarily the anticaptcha API. Ive managed to solve that but I am having some trouble over here. This is my current code:
from time import sleep
from selenium import webdriver
from python_anticaptcha import AnticaptchaClient, NoCaptchaTaskProxylessTask
import os
import time
#Gather Api Key
api_key = 'INSERT API KEY HERE'
#Go to the acc registration site
browser = webdriver.Chrome()
browser.implicitly_wait(5)
browser.get('https://www.reddit.com/register/')
sleep(2)
#Input email
email_input = browser.find_element_by_css_selector("input[name='email']")
email_input.send_keys("INSERT EMAIL HERE")
#Continue to the next part of the registration process
continue_button = browser.find_element_by_xpath("//button[#type='submit']")
continue_button.click()
#Find and input the username and password fields
username_input = browser.find_element_by_css_selector("input[name='username']")
password_input = browser.find_element_by_css_selector("input[name='password']")
username_input.send_keys("INSERT USERNAME HERE")
password_input.send_keys("INSERT PASSWORD HERE")
#Gather site key
url = browser.current_url
site_key = "6LeTnxkTAAAAAN9QEuDZRpn90WwKk_R1TRW_g-JC"
#Acc do the solving process
client = AnticaptchaClient(api_key)
task = NoCaptchaTaskProxylessTask(url, site_key)
job = client.createTask(task)
print("Waiting for recaptcha solution")
job.join()
# Receive response
response = job.get_solution_response()
print(response)
print("Solution has been gotted")
# Inject response in webpage
browser.execute_script('document.getElementById("g-recaptcha-response").innerHTML = "%s"' % (response))
print("Injecting Solution")
# Wait a moment to execute the script (just in case).
time.sleep(1)
print("Solution has been gotted for sure")
# Press submit button
browser.implicitly_wait(10)
Signup = browser.find_element_by_xpath('//input[#type="submit"]')
Signup.click()
Everything runs smoothly except for the final line. I think the program is recognizing the submit button but for some reason gives an element not interactable error. Any help on how to solve this would be greatly appreciated
I had the same issue when I was using selenium. Sometimes it happens that even though selenium has recognized the element, its function is not "ready." Adding a delay before clicking the submit button should fix the issue.

Python selenium chromedriver instsgram keeps asking for code in sms

Has anyone faced the problem that automation routine for instagram written in python with selenium chromedriver has become difficult to run recently because instagram keeps asking for the code it sends in sms or email?
When you do your normal browser login it asks for the code in sms only once. But when you do it with selenium it asks for it every time.
Here is the code
options = webdriver.ChromeOptions()
#options.add_argument('headless')
#options.add_argument('--headless')
options.add_argument('--disable-logging')
options.add_argument('--log-level=3')
driver = webdriver.Chrome(chrome_options=options)
#driver = webdriver.Chrome()
print('Driver started successfully!')
driver.get("https://instagram.com/")
time.sleep(6)
pg=driver.find_element_by_tag_name("html")
lng=pg.get_attribute("lang")
#print(lng)
if lng=='en':
global lin
global foll
global foll_tx
global subscr_tx
lin="Log in"
foll="followers"
foll_tx="Follow"
subscr_tx="following"
get_enter_bt
= driver.find_elements_by_link_text(self.lin)
lin_found=False
while not lin_found:
if len(get_enter_bt)==0:
print('Login not found ((( Refreshing...')
driver.refresh()
time.sleep(6)
get_enter_bt = driver.find_elements_by_link_text(self.lin)
else:
lin_found=True
print('Login button found!')
time.sleep(3)
get_enter_bt[0].click()
time.sleep(3)
#login
login = driver.find_element_by_name("username")
login.send_keys(username)
login = driver.find_element_by_name("password")
login.send_keys(password)
login.send_keys(Keys.RETURN)
time.sleep(9)
get_close_mobapp=driver.find_elements_by_css_selector("button._dbnr9")
if len(get_close_mobapp)!=0:
get_close_mobapp[0].click()
notif_switch=driver.find_elements_by_css_selector("button.aOOlW.HoLwm")
print('notif butt %s' % len(notif_switch))
if len(notif_switch)>0:
notif_switch[0].click()
print(1)
#detect suspicious login
susp_login_msg=driver.find_element_by_xpath("//*[#id=\"react-root\"]/section/div/div/div[1]/div/p")#<p class="O4QwN">Подозрительная попытка входа</p>
print('susm login msg %s' % (susp_login_msg!=None))
if susp_login_msg:
if susp_login_msg.text=='Подозрительная попытка входа':
try:
mobile_button = driver.find_element_by_xpath("//*[#id=\"react-root\"]/section/div/div/div[3]/form/div/div[2]/label")
mobile_button.click()
except:
mobile_button = driver.find_element_by_xpath("//*[#id=\"react-root\"]/section/div/div/div[3]/form/div/div[1]/label")
mobile_button.click()
snd_code_btn=driver.find_element_by_xpath("//*[#id=\"react-root\"]/section/div/div/div[3]/form/span/button")
snd_code_btn.click()
print('Instagram detected an unusual login attempt')
print('A security code was sent to your mobile '+mobile_button.text)
security_code = input('Type the security code here: ')
#security_code_field = driver.find_element_by_xpath(("//input[#id='security_code']"))
security_code_field.send_keys(security_code)
‐----‐‐‐----
This code works fine, but how to stop instagram from asking for the code in sms every time? Does it detect that I run selenium and runs a kind of antibot activity?
I was running the script on schedule to perform series of likes for my subscribers for example which is time consuming you know and automation was my remedy)))

Categories