Send keys control + Shift + click in Selenium with Python - python

I want to select first 100 elements in a list so I user action chain method.
Please suggest any other method, if any. With the code I used below, I can select elements in the list but I am not able to click any element:
for r in range(1, 100):
r = str(r)
print r
row = GlobalVar.Driver.find_element_by_xpath("/html/body/table/tbody/tr[2]/td/table/tbody/tr[2]/td/div/div[3]/table/tbody/tr[2]/td/table/tbody/tr/td[1]/table/tbody/tr[2]/td/select/option["+r+"]")
action_chains = ActionChains(GlobalVar.Driver)
action_chains.key_down(Keys.CONTROL).key_down(Keys.SHIFT).click(row).key_up(Keys.SHIFT).key_up(Keys.CONTROL).perform()

It is a select tag, you can go with select class in python.
ele = GlobalVar.Driver.find_element_by_xpath("/html/body/table/tbody/tr[2]/td/table/tbody/tr[2]/td/div/div[3]/table/tbody/tr[2]/td/table/tbody/tr/td[1]/table/tbody/tr[2]/td/select")
select = Select(ele)
for index in range(1, 100):
select.select_by_index(index)
It is not advisable to use absolute xpath. please try to use relative path if possible or other locator types.

Related

How to get same class name seperately by using css_selector?

I am using the below code to get data from http://www.bddk.org.tr/BultenHaftalik. Two table elements have the same class name. How can I get just one of them?
from selenium import webdriver
import time
driver_path = "C:\\Users\\Bacanli\\Desktop\\chromedriver.exe"
browser = webdriver.Chrome(driver_path)
browser.get("http://www.bddk.org.tr/BultenHaftalik")
time.sleep(3)
Krediler = browser.find_element_by_xpath("//*[#id='tabloListesiItem-253']/span")
Krediler.click()
elements = browser.find_elements_by_css_selector("td.ortala")
for element in elements:
print(element.text)
browser.close()
If you want to select all rows for one column only that match a specific css selection, then you can use :nth-child() selector.
Simply, the code will be like this:
elements = browser.find_elements_by_css_selector("td.ortala:nth-child(2)")
In this way, you will get the "Krediler" column rows only. You can also select the first child if you want to by applying the same idea.
I guess what you want to do is to extract the text and not the numbers, try this:
elements = []
for i in range(1,21):
css_selector = f'#Tablo > tbody:nth-child(2) > tr:nth-child({i}) > td:nth-child(2)'
element=browser.find_element_by_css_selector(css_selector)
elements.append(element)
for element in elements:
print(element.text)
browser.close()

How can I click on an expand button based on criteria using another column with Python and Selenium?

Below is a sample of my script. I am trying to test each row of a column on a site for "World Total". If "World Total" is in this column, then I want to click the expandable button in the same row in the column to the left. This then expands the column and the next "World Total" row will be much lower down. i.e. I have changing XPATHS and I am trying to figure out how to dynamically expand the row when it say world total. Any thoughts?
myElem = WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.XPATH, '//*[#id="ctl00_ContentPlaceHolder1_UltraWebTab1__ctl1_grdExpressQuery_GridView1"]/tbody/tr[3]/td[4]')))
all_rows = driver.find_elements_by_xpath('//*[#id="ctl00_ContentPlaceHolder1_UltraWebTab1__ctl1_grdExpressQuery_GridView1"]/tbody/tr')
country = driver.find_elements_by_xpath('//*[#id="ctl00_ContentPlaceHolder1_UltraWebTab1__ctl1_grdExpressQuery_GridView1"]/tbody/tr/td[4]')
expand = driver.find_elements_by_xpath('//*[#id="ctl00_ContentPlaceHolder1_UltraWebTab1__ctl1_grdExpressQuery_GridView1"]/tbody/tr/td[3]')
for x in range(len(driver.find_elements_by_xpath('//*[#id="ctl00_ContentPlaceHolder1_UltraWebTab1__ctl1_grdExpressQuery_GridView1"]/tbody/tr'))):
if driver.find_elements_by_xpath('//*[#id="ctl00_ContentPlaceHolder1_UltraWebTab1__ctl1_grdExpressQuery_GridView1"]/tbody/tr[' + str(x) + ']/td[4]') == "World Total":
driver.find_elements_by_xpath('//*[#id="ctl00_ContentPlaceHolder1_UltraWebTab1__ctl1_grdExpressQuery_GridView1"]/tbody/tr[' + str(x) + ']/td[3]/input').click()
This should work with some minor changes -
Find elements - returns a collection of elements. so you have to use find_element if you need to find a specific element.
text method returns the text with in the element.
Use try & except to handle the selenium exception ( if the element is not found )
X index starts from 0 by default. you can initialize to 1 depending on your x path.
Code should look like this,
myElem = WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.XPATH, '//*[#id="ctl00_ContentPlaceHolder1_UltraWebTab1__ctl1_grdExpressQuery_GridView1"]/tbody/tr[3]/td[4]')))
all_rows = driver.find_elements_by_xpath('//*[#id="ctl00_ContentPlaceHolder1_UltraWebTab1__ctl1_grdExpressQuery_GridView1"]/tbody/tr')
country = driver.find_elements_by_xpath('//*[#id="ctl00_ContentPlaceHolder1_UltraWebTab1__ctl1_grdExpressQuery_GridView1"]/tbody/tr/td[4]')
expand = driver.find_elements_by_xpath('//*[#id="ctl00_ContentPlaceHolder1_UltraWebTab1__ctl1_grdExpressQuery_GridView1"]/tbody/tr/td[3]')
x=1
for x in range(len(all_rows )):
try:
if driver.find_element_by_xpath('//*[#id="ctl00_ContentPlaceHolder1_UltraWebTab1__ctl1_grdExpressQuery_GridView1"]/tbody/tr[' + str(x) + ']/td[4]').text == "World Total":
driver.find_element_by_xpath('//*[#id="ctl00_ContentPlaceHolder1_UltraWebTab1__ctl1_grdExpressQuery_GridView1"]/tbody/tr[' + str(x) + ']/td[3]/input').click()
except NoSuchElementException:
#Do something here
I ended up going a different route as I had issues arise with the staleness of elements. I knew how many clicks we would be looking for so I used a (5,4,3,2,1) variation of this formula to dynamically select depending on the rows:
driver.find_element_by_xpath('//*[#id="ctl00_ContentPlaceHolder1_UltraWebTab1__ctl1_grdExpressQuery_GridView1"]/tbody/tr[' + str(len(driver.find_elements_by_xpath('//*[#id="ctl00_ContentPlaceHolder1_UltraWebTab1__ctl1_grdExpressQuery_GridView1"]/tbody/tr')) - 1) + ']/td[3]/input').click()

Finding all child elements in an html page using python selenium webdriver

I want to extract all h2 elements of the div element. The code that I've used is this:
browser = webdriver.Chrome()
browser.get("https://www.mmorpg.com/play-now")
time.sleep(2)
item_list_new=[]
link = browser.find_element_by_xpath("//div[#class='freegamelist']")
names = link.find_element_by_tag_name('h2')
x = names.text
item_list_new.append(x)
print(item_list_new)
But when I run this, I only get the first 'h2' element of the div element.
Can somebody tell me what am I doing wrong and also please guide me with the correct way of doing it?
Thanks in advance.
you need to write names = link.find_elements_by_tag_name('h2')
Your code should be
browser = webdriver.Chrome()
browser.get("https://www.mmorpg.com/play-now")
time.sleep(2)
item_list_new=[]
link = browser.find_element_by_xpath("//div[#class='freegamelist']")
names = link.find_elements_by_tag_name('h2')
x = names.text
item_list_new.append(x)
print(item_list_new)
find_element_by_tag_name gives the first element and find_elements_by_tag_name gives all the matching elements
Try to get all header values as below:
link = browser.find_element_by_xpath("//div[#class='freegamelist']")
names = link.find_elements_by_tag_name('h2')
item_list_new = [x.text for x in names]
print(item_list_new)
or you can simplify
names = browser.find_elements_by_xpath("//div[#class='freegamelist']//h2")
item_list_new = [x.text for x in names]
print(item_list_new)
You actually want to use the function find_elements_by_tag_name that sounds almost similar, as pointed out here.

Python selenium - select an element using action chain

I have quite a unique goal and I'm having a hard time to have my python code working. Inside a big selenium application, I'm trying simply to check if an element located on a specific position in the browser corresponds to an element.
For example, if you look at the test website: https://learn.letskodeit.com/p/practice
there's one element (link) labeled "Open Tab" and its coordinates on the browser are: x = 588, y = 576.
This is the code I'm using to confirm in that position I have that element:
target_elem = driver.find_element_by_id("opentab")
print("target elem actual location: {}".format(target_elem.location))
time.sleep(1)
zero_elem = driver.find_element_by_tag_name('body')
x_body_offset = zero_elem.location["x"]
y_body_offset = zero_elem.location["y"]
print("Body coordinates: {}, {}".format(x_body_offset, y_body_offset))
x = 588
y = 576
actions = ActionChains(driver)
actions.move_to_element_with_offset(driver.find_element_by_tag_name('body'), -x_body_offset, -y_body_offset).click()
actions.move_by_offset( x, y ).send_keys(Keys.ESCAPE).perform()
elem_found = driver.switch_to.active_element
print(elem_found.text)
when I print elem_found.text I don't get "Open Tab".
however, if inside the action chain, right before perform(), I add click(), the code above does click on the "Open Tab" link.
Hence my question: can we simply select the element by knowing its exact position in the browser?
I totally understand getting element by location is not really the best way to get element but on my end, I do really need to be able to confirm if an element in position X,Y corresponds to something I expect to find in that location.

Issue selecting dropdown option with selenium webdriver(python)

Trying to make a small script that helps me fill in table
I can't seem to be able to select from a dropdown list using selenium. after running the code multiple times it seems to randomly not work on some rows but it never breaks down at the same spot twice.
For some reason, it works fine on the first 2 dropdown boxes but the last 2 won't seem to work consistently(deductible and company).
heres what I have so far:
from selenium import webdriver
from bs4 import BeautifulSoup
from selenium.webdriver.support.ui import Select
from random import randint
driver = webdriver.Chrome()
driver.get("https://www.ehail.ca/quotes/?1494142398325")
for x in range(5):
driver.find_element_by_name("button").click()
acres = 100
croptype = "Wheat"
qrt = "NW"
sec = randint(1,16)
twn = randint(1,30)
rng = randint(1,30)
mer = "W3"
ded = "Full"
comp = randint(1,7)
cov = 100
for w in range(1,8):
w = str(w)
element = driver.find_element_by_name("acres"+w)
element.send_keys(acres)
select = Select(driver.find_element_by_id('cropComboboxId'+w))
select.select_by_visible_text(croptype)
select = Select(driver.find_element_by_id("quarterComboboxId"+w))
select.select_by_visible_text(qrt)
element = driver.find_element_by_name("section"+w)
element.send_keys(sec)
element = driver.find_element_by_name("township"+w)
element.send_keys(twn)
element = driver.find_element_by_name("range"+w)
element.send_keys(rng)
select = Select(driver.find_element_by_name("meridian"+w))
select.select_by_visible_text(mer)
#THIS IS WHERE THE TROUBLE STARTS!
select = Select(driver.find_element_by_name("deductible"+w))
select.select_by_index(5)
select = Select(driver.find_element_by_name('company'+w))
for index in range(len(select.options)):
select = Select(driver.find_element_by_name('company'+w))
select.select_by_index(1)
element = driver.find_element_by_name("coverageperacre"+w)
element.send_keys(cov)
element = driver.find_element_by_name("quoteForm").submit()
I have tried selecting by index, name, id, text, pretty much everything but I cant even find a consistent breakdown point. in fact the odd time it will run without an error. the error I get is usually though is "cant locate element with index/name/id 'whatever'"
any help would be greatly appreciated.
cheers
The last two dropowns options are populated only after data is filled in previous fields. You can wait until the options exists before choosing from them
options_size = 0
while options_size == 0:
select = Select(driver.find_element_by_name("meridian" + w))
options_size = len(select.options)
select.select_by_visible_text(mer)
The select element is refreshed when populated, so it should be relocated to prevent StaleElementReferenceException

Categories