Selenium only finding some, but not all, related elements - python

I'm attempting to use Selenium to print out a list of users I'm subscribed to on a website, of which there are 3. The following code only prints out the first 2 of the three
from xml.dom.minidom import Element
from selenium import webdriver
from selenium.webdriver.support import wait
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service as ChromeService;
from webdriver_manager.chrome import ChromeDriverManager;
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver import ActionChains
from selenium.webdriver.common.actions.action_builder import ActionBuilder
from selenium.webdriver.common.actions.mouse_button import MouseButton
driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()));
#Chrome client should now start up
driver.get("website-url"); #Go to desired website
title = driver.title;
if title == "WebsiteTitle":
driver.implicitly_wait(5)
email_box = driver.find_element(By.NAME, "email"); #finds username block
pass_box = driver.find_element(By.NAME, "password"); #finds password block
email_box.send_keys('username'); #enter username
pass_box.send_keys('password'); #enter password
submit_button = driver.find_element(By.CSS_SELECTOR, "button[type='submit']"); #finds submit button
submit_button.click(); #clicks it
wait = WebDriverWait(driver, 15);
wait.until(EC.element_to_be_clickable((By.XPATH, "//*[#id='content']/div[1]/div/div/div/div[1]/h1/span"))); #waits 15sec until the "Home" button on the home page can be clicked
def print_subs_list(): #function to print list of users you are subscribed to
driver.get("website-subs-url");
subscriptions_list = driver.find_elements(By.XPATH, "//*[#id='content']/div[1]/div/div[4]/div/div/div[1]/div/div[2]/div/div[2]/div/div[1]/a/div")
for value in subscriptions_list:
print(value.text)
print_subs_list()
driver.quit()
Now, changing the XPath in subscriptions_list to //*[#id='content']/div[1]/div/div[4]/div/div/div[2]/div/div[2]/div/div[2]/div/div[1]/a/div will print out the 3rd result only.
However, my desired result would be to print all of the subscribed users, as there will definitely be more than 3.
How do I change it so that it will print out all of the subscribed users, regardless of the amount?

You identify all the three desired elements using the xpath:
//*[#id='content']/div[1]/div/div[4]/div/div//div/div/div[2]/div/div[2]/div/div[1]/a/div
Your effective line of code will be:
subscriptions_list = driver.find_elements(By.XPATH, "//*[#id='content']/div[1]/div/div[4]/div/div//div/div/div[2]/div/div[2]/div/div[1]/a/div")

Related

Can selenium click on diffrents links?

I want to scrap data from this website(Ignore the perfume that it loads when you scroll down).
For each perfume i want to get its size. In order to see its size I need to click on the perfume which leading me to another page.
Assuming I can get the size of a perfume when Im in its url, How can I make a program that will give me the url of every perfume's page in the website?
This is the code that finds the perfume`s size when I Have the right url:
import gspread
from oauth2client.service_account import ServiceAccountCredentials
from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
urlM = 'https://www.myperfume.co.il/155567-%D7%9B%D7%9C-%D7%94%D7%9E%D7%95%D7%AA%D7%92%D7%99%D7%9D-%D7%9C%D7%92%D7%91' \
'%D7%A8?order=up_title&page=0'
scope = ["https://spreadsheets.google.com/feeds", 'https://www.googleapis.com/auth/spreadsheets',
"https://www.googleapis.com/auth/drive.file", "https://www.googleapis.com/auth/drive"]
creds = ServiceAccountCredentials.from_json_keyfile_name("credentials.json", scope)
client = gspread.authorize(creds)
spreadsheet = client.open("Perfumes")
options = ChromeOptions()
options.headless = True
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
driver.get(# [THE PERFUME'S URL]... )
info = driver.find_element_by_xpath('//*[(#id = "item_current_sub_title")]//span').text
res = ''
for i in info[:info.find('\n')].replace('גודל', ''):
if i.isdigit() or i.isalpha():
res += i
print(res)
Here you will need the following:
Per each product hover over the product to make "more details" and "add to cart" buttons appear.
Click the "more details" button.
In the opened page get the product size (and any other details).
Get back to the main page.
In order to do that for many products you will have to get the list of products again on the main page. Otherwise you will get stale element exception.
So, your code can be something like this:
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
actions = ActionChains(driver)
wait = WebDriverWait(driver, 20)
wait.until(EC.visibility_of_element_located((By.XPATH, "//div[contains(#class,'layout_list_item')]")))
time.sleep(1)
products = driver.find_elements_by_xpath("//div[contains(#class,'layout_list_item')]")
for i in range(len(products)):
wait.until(EC.visibility_of_element_located((By.XPATH, "//div[contains(#class,'layout_list_item')]")))
time.sleep(1)
product = driver.find_elements_by_xpath("//div[contains(#class,'layout_list_item')]")[i]
#hover over the product block
actions.move_to_element(product).perform()
#click the "mode details button
product.find_element_by_xpath(".//p[contains(#class,'extra_button')]").click()
#in the details page get the product sub-title containing the product size
product_size = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div#item_current_sub_title"))).text
#get back to the main page
driver.execute_script("window.history.go(-1)")
UPD
This is exactly what I run:
from selenium import webdriver
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.action_chains import ActionChains
import time
urlM = 'https://www.myperfume.co.il/155567-%D7%9B%D7%9C-%D7%94%D7%9E%D7%95%D7%AA%D7%92%D7%99%D7%9D-%D7%9C%D7%92%D7%91' \
'%D7%A8?order=up_title&page=0'
driver = webdriver.Chrome(executable_path='chromedriver.exe')
wait = WebDriverWait(driver, 20)
actions = ActionChains(driver)
driver.maximize_window()
driver.get(urlM)
wait.until(EC.visibility_of_element_located((By.XPATH, "//div[contains(#class,'layout_list_item')]")))
time.sleep(1)
products = driver.find_elements_by_xpath("//div[contains(#class,'layout_list_item')]")
for i in range(len(products)):
wait.until(EC.visibility_of_element_located((By.XPATH, "//div[contains(#class,'layout_list_item')]")))
time.sleep(1)
product = driver.find_elements_by_xpath("//div[contains(#class,'layout_list_item')]")[i]
#hover over the product block
actions.move_to_element(product).perform()
#click the "mode details button
product.find_element_by_xpath(".//p[contains(#class,'extra_button')]").click()
#in the details page get the product sub-title containing the product size
product_size = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div#item_current_sub_title"))).text
product_size = product_size.split('\n')[0]
print(product_size)
#get back to the main page
driver.execute_script("window.history.go(-1)")
And it prints me the products sizes like גודל: 100 ML

No such element exception Selenium

I'm trying to login to a webpage using Selenium but when I enter the relevant email address and try to click continue I get the no such element exception.
driver = webdriver.Safari()
driver.get('https://manage.statuspage.io/login')
email = driver.find_element_by_id('email')
email.clear()
email.send_keys('XXX')
driver.find_element_by_id("login-btn").click()
driver.find_element_by_id("login-submit").click()
The error occurs on the last line.
As you can see I'm searching for this continue button via id 'login-submit' but it says that it doesn't exist.
Any help would be great!
After clicking
driver.find_element_by_id("login-btn").click()
It takes you to another page where the login-submit element is presented.
But you trying to click this element immediately after clicking on element on previous page while the new page is still not loaded.
You should add a wait to wait for that element on the second page to appear before accessing it.
This should work:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Safari()
wait = WebDriverWait(driver, 20)
driver.get('https://manage.statuspage.io/login')
email = wait.until(EC.visibility_of_element_located((By.ID, "email")))
email.clear()
email.send_keys('XXX')
wait.until(EC.visibility_of_element_located((By.ID, "login-btn"))).click()
wait.until(EC.visibility_of_element_located((By.ID, "login-submit"))).click()
You need to wait for the element/locator to appear on the webpage.
from selenium.webdriver.support import expected_conditions as EC
driver.find_element_by_id("login-btn").click()
login_button = WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located((By.ID, 'login-submit')))
login_button.click()
You can use explicitWait like below to click on the desired button
driver.find_element_by_id("email").send_keys("email")
OR
email = WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.ID, "email")))
email.send_keys('email')
btnLogin = WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.ID,"login-btn")))
btnLogin.click()
import
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
What happened sometime when you send request from a script it returns you page with different ids or class names. After driver.get('https://manage.statuspage.io/login') line save the webpage as .html file and see the id or class name there.

How to login using Selenium

I have one web site like
www.abc.com in this I need to add Email and press continue
and in second page I need to add password and check the check box
so how can I enter the password in 2nd page.
I tired with :
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
uamId = "asas"
driver = webdriver.Chrome("chromedriver")
driver.get("www.abc.com")
print(driver.title)
userid = driver.find_element_by_name("P")
# fill UAM Number
userid.send_keys(a)
elem = driver.find_element_by_xpath('Xpath')
actions = ActionChains(driver)
actions.click(elem).perform()
Before getting the web element you have to validate the element is fully loaded and is clickable / visible.
Also in that specific site you have to click elements in order to insert the email and password.
Your code should look like this:
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
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
driver = webdriver.Chrome("chromedriver")
wait = WebDriverWait(driver, 20)
driver.get("www.abc.com")
print(driver.title)
#open account menu
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".navigation__menu #account span"))).click()
wait.until(EC.visibility_of_element_located((By.XPATH, "//a[text()='Sign in']"))).click()
#now you will have to switch into the iframe
wait.until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[#id='disneyid-iframe']")))
#now you can insert the credentials
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "input[type='email']"))).send_keys(your_email)
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "input[type='password']"))).send_keys(your_password)

Entering into password field using Selenium Webdriver

0
I am trying to do a tutorial and learn Selenium in python however i cant seem to get Selenium to enter the password into the password field/form box. It enters the email addres perfectly fine, and inside the code the password is typed correctly however the website returns it as "Incorrect password entered". However when i type the password in manually it logs in as it is correct. I have removed the email and password for security
I am using:
Python v3.9
Chrome v87
This is the URL i am practicing on:
https://www.aria.co.uk/myAria/ShoppingBasket?action=checkout
And this is my current code:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
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.action_chains import ActionChains
import time
# Open Chromedriver
driver = webdriver.Chrome(r"C:\Users\Ste1337\Desktop\chromedriver\chromedriver.exe")
# Open webpage
driver.get("https://www.aria.co.uk/SuperSpecials/Other+products/ASUS+ROG+Pugio+2+Wireless+Optical+RGB+Gaming+Mouse?productId=72427")
#https://www.aria.co.uk/Products/Components/Graphics+Cards/NVIDIA+GeForce/GeForce+RTX+3060+Ti/Palit+GeForce+RTX+3060+Ti+Dual+8GB+GPU?productId=73054
# Click "Add to Basket" or refresh page if out of stock
try:
element = WebDriverWait(driver, 1).until(EC.presence_of_element_located((By.XPATH, "Out of Stock!")))
time.sleep(5)
browser.refresh()
except:
button = driver.find_element_by_id("addQuantityButton")
button.click()
basket = WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.ID, "basketContent")))
basket.click()
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//img[contains(#src,'/static/images/checkoutv2.png')]"))).click()
login = WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.NAME,"login[email]")))
login.send_keys("testuser#hotmail.co.uk")
login.send_keys(Keys.TAB)
driver.implicitly_wait(2)
login.send_keys("password")
driver.implicitly_wait(2)
login.send_keys(Keys.ENTER)
You haven't defined somewhere to put the password. Currently, the password in MEANT to be entered in the same place as the email. To change that, define where the password is meant to go. This is how I did it:
passwrd = driver.find_element_by_xpath("/html/body/div[4]/div[1]/div[2]/form/div/h1/div[3]/div/div/input[2]")
passwrd.send_keys("password")
So in total, the code should look like this:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
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.action_chains import ActionChains
import time
# Open Chromedriver
driver = webdriver.Chrome(r"C:\Users\eesam\AppData\Local\Programs\Python\Python39\Scripts\chromedriver.exe")
# Open webpage
driver.get("https://www.aria.co.uk/SuperSpecials/Other+products/ASUS+ROG+Pugio+2+Wireless+Optical+RGB+Gaming+Mouse?productId=72427")
#https://www.aria.co.uk/Products/Components/Graphics+Cards/NVIDIA+GeForce/GeForce+RTX+3060+Ti/Palit+GeForce+RTX+3060+Ti+Dual+8GB+GPU?productId=73054
# Click "Add to Basket" or refresh page if out of stock
try:
element = WebDriverWait(driver, 1).until(EC.presence_of_element_located((By.XPATH, "Out of Stock!")))
time.sleep(5)
browser.refresh()
except:
button = driver.find_element_by_id("addQuantityButton")
button.click()
basket = WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.ID, "basketContent")))
basket.click()
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//img[contains(#src,'/static/images/checkoutv2.png')]"))).click()
login = WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.NAME,"login[email]")))
login.send_keys("testuser#hotmail.co.uk")
login.send_keys(Keys.TAB)
driver.implicitly_wait(2)
passwrd = driver.find_element_by_xpath("/html/body/div[4]/div[1]/div[2]/form/div/h1/div[3]/div/div/input[2]")
passwrd.send_keys("password")
driver.implicitly_wait(2)
login.send_keys(Keys.ENTER)

Can't select "All Filters" in LinkedIn after I get to People Search - Find_element does not work no matter what I try

Wrote simple python code to do the following:
1.login into linkedin
2. click search, then people
3. click "All Filters" to further modify search
I am getting stuck on step 3 and am unable to get driver to select and click on "All Filters"
I have tried to find_element by xpath, however it is dynamic and changes
I have tried to find_element by text "All Filters" and still doesn't work
For some reason when I right click on "All Filters" button and click Inspect, it first takes me to instead of the actual button; I have to right click - inspect a 2nd time to get to ; This makes me think the button is hidden and I am unsure of how to proceed.
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
import pynput.mouse as ms
import pynput.keyboard as kb
import time
driver = webdriver.Chrome("C:/Users/akame/Documents/PythonFiles/chromedriver.exe")
act = ActionChains(driver)
driver.get ('https://www.linkedin.com/')
driver.maximize_window()
login_email = driver.find_element_by_id('login-email')
login_password = driver.find_element_by_id('login-password')
submit1 = driver.find_element_by_id('login-submit')
mouse = ms.Controller()
keyboard = kb.Controller()
login_email.send_keys(‘XXXXX’)
login_password.send_keys('XXXXXX')
submit1.send_keys(u'\ue007')
searchfield = driver.find_element_by_xpath('//*[#id="ember49"]/input')
act.click(searchfield).perform()
act.send_keys(Keys.ARROW_DOWN).perform()
act.send_keys(Keys.ENTER).perform()
time.sleep(5)
#this is where it does not work--->
button_af = driver.find_element_by_text('All Filters')
button_af.click()
try code below, or just replace button_af = driver.find_element_by_text('All Filters') with button_af=find_element_by_xpath("//span[#class='artdeco-button__text' and text()='All Filters']"), cause sometime there's newline\r or \n in an element text, u should alway try to use contains instead of == to get an element's text:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time
email = "ur_email"
pwd = "ur_pwd"
driver = webdriver.Chrome()
act = ActionChains(driver)
driver.get ('https://www.linkedin.com/')
login_email = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "login-email"))
)
login_password = driver.find_element_by_id('login-password')
submit1 = driver.find_element_by_id('login-submit')
login_email.send_keys(email)
login_password.send_keys(pwd)
submit1.click()
searchfield = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//input[#role='combobox']")))
searchfield.click()
searchKeywordXpath = "//span[text()='People']"
searchKeyword = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, searchKeywordXpath)))
searchKeyword.click()
btnAllFilterXpath = "//span[#class='artdeco-button__text' and text()='All Filters']"
btnAllFilter = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, btnAllFilterXpath)))
btnAllFilter.click()
# just debug code: wait to see the right page appear or not
time.sleep(10)

Categories

Resources