How to find button with Selenium by its text inside (Python)? - python

I have the following three buttons that I can't figure out how to grab the text that is inside of them (e.g Outliers). I tried browser.find_element_by_link_text("Outliers").click(), but got "Unable to locate element" error. How can I do it?

See: find_element_by_* commands are deprecated in selenium
In newer versions of selenium try:
from selenium.webdriver.common.by import By
browser.find_element(By.XPATH, '//button[text()="Outliers"]')
older versions of selenium:
browser.find_element_by_xpath('//button[text()="Outliers"]')
To update ALL of the older versions I found a nifty regex here, and then just fixup the import:
https://stackoverflow.com/a/70586710/2026508

There are two ways :
By using text() method:
browser.find_element(By.XPATH,'//button[text()="Outliers"]')
By using normalize-space() method:
browser.find_element(By.XPATH, '//button[normalize-space()="Outliers"]')
Note : It is always better to use normalize-space() method as it will work even if there are spaces present at the start of your text or at the end of text, because normalize-space() method trim the left and right side spaces
For More information on Normalize-space()

Try this XPath:
"//button[#class='three-state-item btn btn-default'][.='Outliers']".

This is the solution that worked for me:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
CHROME_DRIVER_PATH = Your Driver Path
USERNAME = YOUR USERNAME
PASSWORD = YOUR PASSWORD
SIMILAR_ACCOUNT = "idogsplanet"
class InstaFollower:
def __init__(self, driver_path):
self.driver = webdriver.Chrome(executable_path=driver_path)
def login(self):
self.driver.get("https://www.instagram.com/accounts/login/")
time.sleep(3)
username = self.driver.find_element_by_name("username")
username.send_keys(USERNAME)
password = self.driver.find_element_by_name("password")
password.send_keys(PASSWORD)
time.sleep(2)
login = self.driver.find_element_by_xpath('//*[#id="loginForm"]/div/div[3]/button/div')
login.click()
def find_followers(self):
time.sleep(5)
self.driver.get("https://www.instagram.com/" + SIMILAR_ACCOUNT + "/followers")
followers = self.driver.find_element_by_xpath('//*[#id="react-root"]/section/main/div/header/section/ul/li[2]/a')
followers.click()
time.sleep(1)
def follow(self):
all_buttons = self.driver.find_elements_by_xpath('//button[normalize-space()="Follow"]')
modal = self.driver.find_element_by_xpath('/html/body/div[5]/div/div/div[2]')
for button in all_buttons:
if button.text != "Follow":
pass
else:
button.click()
time.sleep(2)
time.sleep(10)
self.driver.execute_script("arguments[0].scrollTop = arguments[0].scrollHeight", modal)
self.follow()
bot = InstaFollower(CHROME_DRIVER_PATH)
bot.login()
bot.find_followers()
bot.follow()

Related

Webdriver ( Selenium ) Cannot find the element

`
import requests
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from time import sleep
import os
login_page = "https://fap.fpt.edu.vn/Default.aspx"
# page = "https://fap.fpt.edu.vn/Report/ScheduleOfWeek.aspx"
email = ""
password = ""
options = Options()
options.add_argument("--window-size=1920,1080")
options.binary_location = "C:\Program Files\Google\Chrome\Application\chrome.exe"
driver = webdriver.Chrome(options = options)
driver.get(login_page)
login1 = driver.find_element("xpath","//div[#class='abcRioButtonContentWrapper']").click()
driver.find_element(By.NAME, "identifier").send_keys(email)
sleep(3)
driver.find_element(By.ID, "identifierNext").click()
sleep(2)
driver.find_element(By.NAME, "password").send_keys(password)
sleep(2)
driver.find_element(By.ID, "passwordNext").click()
sleep(999999)
`
I believe i chose the right By.NAME ( "indentifier" ) but the code still not work and return message no such element.
I tried to change the syntax, using xpath change By.NAME to By.ID but it still not work
Google login page opens in a new window. So you need to switch to this window before interacting with it. So you need to use this code (the first and the last lines are from your code and between is the part you need to add):
login1 = driver.find_element("xpath","//div[#class='abcRioButtonContentWrapper']").click()
windows = driver.window_handles
driver.switch_to.window(windows[1])
driver.find_element(By.NAME, "identifier").send_keys(email)
And after you've finished with the login you will need to switch back to the main window. To do that you can use this code:
driver.switch_to.window(windows[0])
And then work with the content of the page
No, don't use name of jsname here, because they get filled with random data.
Just find your Google account name or your email address by text and click it:
userAccount = driver.find_element_by_xpath("//*[text()='YourGoogleAccountName']")
userAccount.click()

Selenium cant use the find_element_by_css_selector()

The Situation:
Firstly I would like to say that am new to selenium and decided to pick it up to practice some python. I am currently following a tutorial online and decided to make a youtube bot.
The Code:
from selenium import webdriver
from selenium.webdriver.chrome.webdriver import WebDriver
import time
import random
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
def login_with_username_and_password(browser, username, password):
# FILL UP THE LOGIN FORM
email_input = browser.find_elements('input[type=email]')
email = username
for letter in email:
email_input.send_keys(letter)
wait_time = random.randint(0,1000)/1000
time.sleep(wait_time)
next_button = browser.find_elements_by_css_selector("button")
time.sleep(2)
next_button[2].click()
time.sleep(2)
password_input = browser.find_element_by_css_selector('input[type=password]')
password = password
for letter in password:
password_input.send_keys(letter)
wait_time = random.randint(0,1000)/1000
time.sleep(wait_time)
next_button = browser.find_elements_by_css_selector("button")
time.sleep(2)
next_button[1].click()
confirm_button = browser.find_elements_by_css_selector("div[role=button]")
time.sleep(2)
if(len(confirm_button)>0):
confirm_button[1].click()
def click_on_agree_and_signin(browser):
# agree_button= browser.find_element_by_css_selector('button')
# time.sleep(2)
# agree_button.click()
signin_buttons= browser.find_elements_by_css_selector(".signin")
time.sleep(6) # Wait longer so the message pops up
while(len(signin_buttons)== 0):
signin_buttons= browser.find_elements_by_css_selector(".signin")
time.sleep(1)
signin_buttons[0].click()
def enter_search_term(browser,search_term):
# Enter text on the search term
search_input = browser.find_element_by_id("search")
for letter in search_term:
search_input.send_keys(letter)
wait_time = random.randint(0,1000)/1000
time.sleep(wait_time)
search_input.send_keys(Keys.ENTER)
def enter_comment(browser, comment):
comment_input = browser.find_element_by_css_selector("ytd-comment-simplebox-renderer")
entering_comment_actions = ActionChains(browser)
entering_comment_actions.move_to_element(comment_input)
entering_comment_actions.click()
for letter in comment:
entering_comment_actions.send_keys(letter)
wait_time = random.randint(0,1000)/1000
entering_comment_actions.pause(wait_time)
entering_comment_actions.perform()
time.sleep(1)
send_comment_button = browser.find_element_by_id("submit-button")
send_comment_button.click()
###########################################
# BOT STARTS HERE #
###########################################
driver=webdriver.Chrome()
driver.maximize_window
driver.get("https://www.youtube.com/")
all_search_terms = ['online marketing']
# Click Agree and Sing In
click_on_agree_and_signin(driver)
# Sign In
login_with_username_and_password(driver, "hey289895#gmail.com", "-1qa2ws3ed4rf-")
for search_term in all_search_terms:
enter_search_term(driver, search_term)
time.sleep(2)
thumbnails = driver.find_element_by_css_selector("ytd-video-renderer")
for index in range(1, 6):
thumbnails[index].click()
time.sleep(6)
enter_comment(driver, "love it")
driver.execute_script("window.history.go(-1)")
thumbnails = driver.find_element_by_css_selector("ytd-video-renderer")
time.sleep(1)
driver.close()
The Problem:
When Running this code it produces an error related to the find_element_by_css_selector method. Most frequently during the sign in phase as shown here.
The Question:
Can anybody explain what is going on here and where I am going wrong, as well as how I can fix this please.
First: it is only warning, not error.
In my version 3.141.0 I can use both methods
from selenium import webdriver
driver = webdriver.Chrome() # Firefox()
driver.find_elements_by_css_selector(...)
driver.find_elements_by_xpath(...)
# etc.
and
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome() # Firefox()
driver.find_elements(By.CSS_SELECTOR, ...)
driver.find_elements(By.XPATH, ...)
# etc.
but it seems they plan to remove functions find_elements_by_... in the future (in versions 4.x) and now find_elements_by_... still works but it shows warning that you should use second method find_elements(By.CSS_SELECTOR, ...).
You could use module warnings to hide these warnings but better start using only second method.
BTW:
In source code for find_elements_by_css_selector you can see it runs warning.warn(...) and next it runs find_elements(By.CSS_SELECTOR, ...)
To check what version you use
import selenium
print(selenium.__version__)

Message: Unable to locate elemen? [duplicate]

I want to log in to instagram using selenium, but I can't seem to enter values into the fields.
Here's my script:
#go to this address
browser.get('https://www.instagram.com')
#sleep for 1 seconds
sleep(1)
#find the 'login' button on homepage
login_elem = browser.find_element_by_xpath(
'//*[#id="react-root"]/section/main/article/div[2]/div[2]/p/a')
#navigate to login page
login_elem.click()
Having trouble from here onwards:
#locate the username field within the form
unform = browser.find_element_by_xpath(
'//*[#id="f3b8e6724a27994"]')
#clear the field
textunform.clear()
#enter 'test' into field
unform.send_keys('test')
There is a trick in this, instead of searching for the Button (Log In) there is a better way to log in without it. how? let's see:
Import the packages you need:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from time import sleep
#Select the driver, In our case we will use Chrome.
chromedriver_path = 'chromedriver.exe' # Change this to your own chromedriver path!
webdriver = webdriver.Chrome(executable_path=chromedriver_path)
sleep(2)
webdriver.get('https://www.instagram.com/accounts/login/?source=auth_switcher')
sleep(3)
username = webdriver.find_element_by_name('username')
username.send_keys('yourUsername')
password = webdriver.find_element_by_name('password')
password.send_keys('yourPassword')
#instead of searching for the Button (Log In) you can simply press enter when you already selected the password or the username input element.
submit = webdriver.find_element_by_tag_name('form')
submit.submit()
You can copy the code and run it directly (even without a real username or password)
To get the webdriver (chromedriver.exe) from ChromeDriver
The instagram is applying some method to leave the dynamic id, xpath and css, every time a reload happens on the page the attributes change their values, being more difficult to click or to set values:
I solved it:
#Locate the username field
unform = browser.find_element_by_name("username")
#Locate the password field
pwform = browser.find_element_by_name('password')
ActionChains(browser)\
.move_to_element(unform).click()\
.send_keys('test')\
.move_to_element(pwform).click()\
.send_keys('test')\
.perform()
#Locate login button
login_button = browser.find_element_by_xpath(
'//*[#id="react-root"]/section/main/article/div[2]/div[1]/div/form/span/button')
#Click login button
login_button.click()
The username field on Instagram is a ReactJS so you have to induce WebDriverWait and then invoke send_keys() method as follows :
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
options = Options()
options.add_argument("start-maximized")
options.add_argument("disable-infobars")
options.add_argument("--disable-extensions")
browser = webdriver.Chrome(chrome_options=options, executable_path=r'C:\path\to\chromedriver.exe')
browser.get('https://www.instagram.com')
login_elem = browser.find_element_by_xpath('//*[#id="react-root"]/section/main/article/div[2]/div[2]/p/a')
login_elem.click()
WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input[name='username']"))).send_keys("anon")
Browser Screenshot :
In this case IMHO it's better to use this: browser.find_element_by_name("Bermil18") / browser.find_element_by_name("1q56y3w5t9k0p3es8i1q")
Here's my solution for Sign In on Instagram
def login(self, username, password):
""" Methods that log in to Instagram by taking user's credentials as parameters"""
self.driver.get("https://www.instagram.com/accounts/login/")
try:
self.driver.find_element_by_xpath("//input[#name=\"username\"]").send_keys(username) # filling username
self.driver.find_element_by_xpath("//input[#name=\"password\"]").send_keys(password) # filling password
self.driver.find_element_by_xpath("//button[#type=\"submit\"]").click() # submit form
except NoSuchElementException:
print("Failed to log in: Unable to locate Username/Password/LogIn element(s)")
# If login is unsuccessful, Instagram will show a message "Sorry, your password was incorrect. Please double-check your password."
success = self.driver.find_elements_by_xpath("//p[#id = \"slfErrorAlert\"]")
if len(success) == 0:
print("Login successful!")
else:
print("Sorry, sign in unsuccessful. Please double-check your credentials.")
See my Github repo for more: https://github.com/mlej8/InstagramBot
def login(username,password):
driver.get(base_url)
time.sleep(3)
detail = driver.find_elements_by_class_name('_2hvTZ')
detail[0].clear()
detail[1].clear()
detail[0].send_keys(username)
detail[1].send_keys(password)
driver.find_element_by_class_name('L3NKy').click()
time.sleep(3)
for i in driver.find_elements_by_tag_name('button'):
if i.text=='Not Now':
i.click()
break
time.sleep(3)
driver.find_element_by_class_name('HoLwm').click()
base url is intagram url .
I have a made an instabot and you can find the code for logging in ,follow, unfollow ,like ,check posts in recent day ,etc in the following github link.
https://github.com/Devanshchowdhury2212/Instagram-Web-scraping-
This worked for me:
def login(self, username):
self.driver = webdriver.Chrome()
self.driver.get('https://www.instagram.com/')
sleep(1)
username_input = self.driver.find_element_by_xpath(
"//input[#name='username']")
username_input.send_keys(username)
password_input = self.driver.find_element_by_xpath(
"//input[#name='password']")
password_input.send_keys(pw)
submit_btn = self.driver.find_element_by_xpath(
"//button[#type='submit']")
submit_btn.click()
sleep(2)
save_your_login_info_not_now = self.driver.find_element_by_xpath("/html/body/div[1]/section/main/div/div/div/div/button")
save_your_login_info_not_now.click()
You will notice that i am sending the variable pw instead of my actual password. This is for security reasons. Make a new file called secrets.py and inside it, declare your password in the following format:
pw = '*********'
Try to select the field with
unform = browser.find_element_by_xpath("//input[#name='username']")
unform.send_keys(<username>)
and for password
browser.find_element_by_xpath("//input[#name='password']")

Find elements by input type

I'm trying Python and Selenium. My goal is to log myself into Discord (https://discordapp.com/login. But here is the problem. I can't manage to get the email and password box selected. But the worst part is trying to select a textbox on a server... I tried everything, even locating by XPath, but I can't seem to do it right. Also, doing it on ATOM is probably not the best idea since I don't get any error messages :P. Here is a snippet to select the email textbox.
from selenium
import webdriver
from selenium.webdriver.common.keys
import Keys
browser = webdriver.Firefox()
browser.get('https://discordapp.com/login')
assert 'discordapp' in browser.title
elem = browser.find_element_by_name('textarea')# this is the part where i need help
elem.send_keys('test' + Keys.ENTER)
For email this css selector should work :
input[type='email']
For password :
input[type='password']
I've tested this code :
browser.get("https://discordapp.com/login")
elem = browser.find_element_by_css_selector("input[type='email']")# this is the part where i need help
elem.send_keys("itsolidude#imail.com")
elem1 = browser.find_element_by_css_selector("input[type='password']")# this is the part where i need help
elem1.send_keys("password")
login_button = browser.find_element_by_xpath("//div[text()='Login']/parent::button")
login_button.click()
This worked fine on my machine.
you need to check the div container and add them into the xpath.
Try the following code and please debug the indents, in case that stackoverflow is not transferring them properly (well, I don't know how to do it nice and correctly.)
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
class loginPage():
def test(self):
baseUrl = 'https://discordapp.com/login'
driver = webdriver.Firefox(executable_path="G:\\webdriver/geckodriver.exe")
driver.maximize_window()
driver.implicitly_wait(5)
driver.get(baseUrl)
mail = driver.find_element(By.XPATH, "//div[3]/div[1]/div/input[contains(#type,'email')]")
time.sleep(5)
mail.send_keys("test#gmail.com")
time.sleep(3)
print("Enter mail adress")
password = driver.find_element(By.XPATH, "//div[3]/div[2]/div/input[contains(#type,'password')]")
time.sleep(5)
password.send_keys("123456789")
time.sleep(3)
print("Enter password")
time.sleep(10)
driver.quit()
ff = loginPage()
ff.test()
Login To Discord Website using Python and Selenium:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
driver = webdriver.Chrome()
driver.get("https://discord.com/login")
time.sleep(6)
username_input = driver.find_element_by_name('email')
username_input.send_keys("enter-your-username-here")
password_input = driver.find_element_by_name('password')
password_input.send_keys("Enter-your-password-here")
login_button = driver.find_element_by_xpath('//*[#id="app-mount"]/div[2]/div/div[2]/div/div/form/div/div/div[1]/div[3]/button[2]')
login_button.click()

Filling in login forms in Instagram using selenium and webdriver (chrome) python OSX

I want to log in to instagram using selenium, but I can't seem to enter values into the fields.
Here's my script:
#go to this address
browser.get('https://www.instagram.com')
#sleep for 1 seconds
sleep(1)
#find the 'login' button on homepage
login_elem = browser.find_element_by_xpath(
'//*[#id="react-root"]/section/main/article/div[2]/div[2]/p/a')
#navigate to login page
login_elem.click()
Having trouble from here onwards:
#locate the username field within the form
unform = browser.find_element_by_xpath(
'//*[#id="f3b8e6724a27994"]')
#clear the field
textunform.clear()
#enter 'test' into field
unform.send_keys('test')
There is a trick in this, instead of searching for the Button (Log In) there is a better way to log in without it. how? let's see:
Import the packages you need:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from time import sleep
#Select the driver, In our case we will use Chrome.
chromedriver_path = 'chromedriver.exe' # Change this to your own chromedriver path!
webdriver = webdriver.Chrome(executable_path=chromedriver_path)
sleep(2)
webdriver.get('https://www.instagram.com/accounts/login/?source=auth_switcher')
sleep(3)
username = webdriver.find_element_by_name('username')
username.send_keys('yourUsername')
password = webdriver.find_element_by_name('password')
password.send_keys('yourPassword')
#instead of searching for the Button (Log In) you can simply press enter when you already selected the password or the username input element.
submit = webdriver.find_element_by_tag_name('form')
submit.submit()
You can copy the code and run it directly (even without a real username or password)
To get the webdriver (chromedriver.exe) from ChromeDriver
The instagram is applying some method to leave the dynamic id, xpath and css, every time a reload happens on the page the attributes change their values, being more difficult to click or to set values:
I solved it:
#Locate the username field
unform = browser.find_element_by_name("username")
#Locate the password field
pwform = browser.find_element_by_name('password')
ActionChains(browser)\
.move_to_element(unform).click()\
.send_keys('test')\
.move_to_element(pwform).click()\
.send_keys('test')\
.perform()
#Locate login button
login_button = browser.find_element_by_xpath(
'//*[#id="react-root"]/section/main/article/div[2]/div[1]/div/form/span/button')
#Click login button
login_button.click()
The username field on Instagram is a ReactJS so you have to induce WebDriverWait and then invoke send_keys() method as follows :
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
options = Options()
options.add_argument("start-maximized")
options.add_argument("disable-infobars")
options.add_argument("--disable-extensions")
browser = webdriver.Chrome(chrome_options=options, executable_path=r'C:\path\to\chromedriver.exe')
browser.get('https://www.instagram.com')
login_elem = browser.find_element_by_xpath('//*[#id="react-root"]/section/main/article/div[2]/div[2]/p/a')
login_elem.click()
WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input[name='username']"))).send_keys("anon")
Browser Screenshot :
In this case IMHO it's better to use this: browser.find_element_by_name("Bermil18") / browser.find_element_by_name("1q56y3w5t9k0p3es8i1q")
Here's my solution for Sign In on Instagram
def login(self, username, password):
""" Methods that log in to Instagram by taking user's credentials as parameters"""
self.driver.get("https://www.instagram.com/accounts/login/")
try:
self.driver.find_element_by_xpath("//input[#name=\"username\"]").send_keys(username) # filling username
self.driver.find_element_by_xpath("//input[#name=\"password\"]").send_keys(password) # filling password
self.driver.find_element_by_xpath("//button[#type=\"submit\"]").click() # submit form
except NoSuchElementException:
print("Failed to log in: Unable to locate Username/Password/LogIn element(s)")
# If login is unsuccessful, Instagram will show a message "Sorry, your password was incorrect. Please double-check your password."
success = self.driver.find_elements_by_xpath("//p[#id = \"slfErrorAlert\"]")
if len(success) == 0:
print("Login successful!")
else:
print("Sorry, sign in unsuccessful. Please double-check your credentials.")
See my Github repo for more: https://github.com/mlej8/InstagramBot
def login(username,password):
driver.get(base_url)
time.sleep(3)
detail = driver.find_elements_by_class_name('_2hvTZ')
detail[0].clear()
detail[1].clear()
detail[0].send_keys(username)
detail[1].send_keys(password)
driver.find_element_by_class_name('L3NKy').click()
time.sleep(3)
for i in driver.find_elements_by_tag_name('button'):
if i.text=='Not Now':
i.click()
break
time.sleep(3)
driver.find_element_by_class_name('HoLwm').click()
base url is intagram url .
I have a made an instabot and you can find the code for logging in ,follow, unfollow ,like ,check posts in recent day ,etc in the following github link.
https://github.com/Devanshchowdhury2212/Instagram-Web-scraping-
This worked for me:
def login(self, username):
self.driver = webdriver.Chrome()
self.driver.get('https://www.instagram.com/')
sleep(1)
username_input = self.driver.find_element_by_xpath(
"//input[#name='username']")
username_input.send_keys(username)
password_input = self.driver.find_element_by_xpath(
"//input[#name='password']")
password_input.send_keys(pw)
submit_btn = self.driver.find_element_by_xpath(
"//button[#type='submit']")
submit_btn.click()
sleep(2)
save_your_login_info_not_now = self.driver.find_element_by_xpath("/html/body/div[1]/section/main/div/div/div/div/button")
save_your_login_info_not_now.click()
You will notice that i am sending the variable pw instead of my actual password. This is for security reasons. Make a new file called secrets.py and inside it, declare your password in the following format:
pw = '*********'
Try to select the field with
unform = browser.find_element_by_xpath("//input[#name='username']")
unform.send_keys(<username>)
and for password
browser.find_element_by_xpath("//input[#name='password']")

Categories