Unable to extract an attribute using the Selenium package - python

The general idea is to extract DOM using Selenium packages.
Specifically, the objective is to extract the value of max which reside in the class pagination__input hide-phone as shown below
<div class="pagination__input hide-phone">
<input type="number" name="page" max="12" value="1">
</div>
The website is accessible from this link.
To achieve this, the following code were drafted.
maxPage = self.browser.find_elements_by_css_selector( "[class='pagination__input hide-phone']" )
valueMax=maxPage.get_attribute( 'max' )
However, the following error was thrown.
AttributeError: 'list' object has no attribute 'get_attribute'
May I know what is the problem.
Thanks in advance.
Edit 2
As suggested by #Kunduk.
As per #Kunduk, the following line has been tailor accordingly. Specifically, add the self.
print( WebDriverWait( self.browser, 10 ).until( EC.visibility_of_element_located(
(By.CSS_SELECTOR, "div.pagination__input.hide-phone>input[name='page']") ) ).get_attribute( "max" ) )
However, I got the following error
Edit 1:
As suggested by #Josh
pages = self.browser.find_elements_by_css_selector( "[class='pagination__input hide-phone']" )
maxPages = [page for page in pages if page.get_attribute('max')]
However, it return the result of [],also as shown by the figure below:

Use this selector div.pagination__input > input and induce WebDriverWait() :
driver.get('https://www.freepik.com/search?dates=any&format=search&page=1&query=Polygonal%20Human&sort=popular')
element = WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.CSS_SELECTOR, 'div.pagination__input > input')))
print(element.get_attribute('max'))

To get the max value of the page induce WebDriverWait() and wait for presence_of_element_located() and following css selector.
driver.get("https://www.freepik.com/search?dates=any&format=search&page=1&query=Polygonal%20Human&sort=popular")
print(WebDriverWait(driver,10).until(EC.presence_of_element_located((By.CSS_SELECTOR,"div.pagination__input.hide-phone>input[name='page']"))).get_attribute("max"))
You need to import following libraries.
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
snapshpt:

Related

Finding value using Xpath (with no unique identifiers) in Python Selenium

I'm having trouble trying to get the colour of a vehicle in Selenium using Python. I've checked YouTube, stackoverflow and all the usual resources but can't seem to find an answer that makes sense (I'm relatively new to Python and Selenium). I'm currently undertaking a project to automate the fetching of vehicle colour from the gov.uk website into an excel sheet based on the Vehicle Registration number already present on the spreadsheet. The code isn't finished yet, as I want to get over this Xpath hurdle first!
I need to fetch the 'Blue' value from this code:
<dl class="summary-no-action">
<div class="govuk-summary-list__row">
<dt>Registration number</dt>
<dd>
<div class="reg-mark-sm">WJ06 HYF</div>
</dd>
</div>
<div class="govuk-summary-list__row">
<dt>Make</dt>
<dd>VOLKSWAGEN</dd>
</div>
<div class="govuk-summary-list__row">
<dt>Colour</dt>
<dd>BLUE</dd>
</div>
</dl>
However, as you can see, they have made it very difficult as there is no specific ID, class, tag name, etc to work with so I'm assuming Xpath is my only option? could anyone help me as to the best implementation of this? My assumption is to find the first 'dd' tag underneath 'Colour' but I don't know how to write this!
Here is the code snippet I'm working on that I have so far:
try:
main = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CLASS_NAME, "summary-no-action"))
)
div = main.find_element(By.LINK_TEXT, "Colour")
for article in div:
header = article.find_element(By.TAG_NAME, "dd")
print(header.text)
finally:
driver.quit()
I'm aware the line 'div = main.find_element(By.LINK_TEXT, "Colour")' is incorrect, but I need to replace it with something so that I may fetch the colour present in the 'dd' tag underneath.
This is what I had originally, but it brings back all the values in the "summary-no-action" class name:
try:
main = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CLASS_NAME, "summary-no-action"))
)
div = main.find_elements(By.CLASS_NAME, "govuk-summary-list__row")
for article in div:
header = article.find_element(By.TAG_NAME, "dd")
print(header.text)
finally:
driver.quit()
Any help would be appreciated!
EDIT:
For reference, here is the whole code:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
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
import time
driver =
webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("https://www.google.com")
driver.get ("https://vehicleenquiry.service.gov.uk/")
time.sleep(5)
search = driver.find_element(By.ID ,
"wizard_vehicle_enquiry_capture_vrn_vrn")
search.send_keys("wj06hyf")
search.send_keys(Keys.RETURN)
try:
main = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CLASS_NAME, "summary-no-action"))
)
div = main.find_elements(By.CLASS_NAME, "govuk-summary-list__row")
for article in div:
header = article.find_element(By.TAG_NAME, "dd")
print(header.text)
finally:
driver.quit()
Use the following xpath to get the value BLUE. first identify the dt tag with text colour and following dd tag
//dt[text()='Colour']/following::dd[1]
code:
print(WebDriverWait(driver,10).until(EC.visibility_of_element_located((By.XPATH, "//dt[text()='Colour']/following::dd[1]"))).text)
To fetch the text Blue you need to induce WebDriverWait for the visibility_of_element_located() and you can use either of the following locator strategies:
Using CSS_SELECTOR and get_attribute("innerHTML"):
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "dl.summary-no-action div:last-child dd"))).get_attribute("innerHTML"))
Using XPATH and text attribute:
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//dl[#class='summary-no-action']//div[#class='govuk-summary-list__row']/dt[text()='Colour']//following-sibling::dd[1]"))).text)
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

Unable to Locate Element with Selenium Python despite xPath

I can't locate element on website and insert numerical value inside using Selenium on Firefox with Python.
I am using firefox add-in to get the xPath for the input field, I receive:
/html/body/div1/section/div/div/div/div/form/div1/div/div[4]/div2/div/div/div/div1/div1/table/tbody/tr1/td3/div/input
however with Python code objDriver.find_element_by_xpath("...") - I receive "Unable to locate element:" -> like xpath is wrong
If I use it on the let's say border of the input field, I get following xPath:
/html/body/div1/section/div/div/div/div/form/div1/div/div[4]/div2/div/div/div/div1/div1/table/tbody/tr1/td3
This element I can allocate using objDriver.find_element_by_xpath("...") but it is not input field, so I can't insert value
If I click "Inspect" in Firefox, I get:
CSS Path:
html body div.main-content section.section div.block-one_col_1 div.container-fluid.wrapper div.row div.col-12 form#id_form-process.form-horizontal.formfactory div.row div.col-md div#fieldgroup_variants.fieldset div#fieldgroup_variants__fields.fieldset__content div.form-group.row.formfield_variantsCalculator.fieldpk_2533.mb-0.is-valid div.col-md-6.col-12 div.d-flex.flex-row div.w-100 div.table-scroll table.table.table--step tbody#tableContent.table tr.table-row.table-row--count td div.form-group.group1 input.form-control.variant-value.variant1.touched
xPath:
/html/body/div/section/div/div/div/div/form/div[1]/div/div[4]/div[2]/div/div/div/div[1]/div[1]/table/tbody/tr[1]/td[3]/div/input
HTML part I am interested in:
<td data-risk="6.1"><div class="form-group group1" data-excluded="false" data-risk="6.1"><input name="1" class="form-control variant-value variant1 touched" data-editable="true" data-risk="6.1" data-visible-sum="true" data-dynamic="false"></div></td>
Do you have any idea how can I locate the field I need?
General view of Input field:
When getting xPath of the border:
When getting xPath of the Input field:
Can you try with the below xpath with Explicit waits :
wait = WebDriverWait(driver, 10)
wait.until(EC.element_to_be_clickable((By.XPATH, "//input[#name= '1' and contains(#class, 'variant-value')]"))).send_keys('10000')
Imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Try with xPath = //input[#class="form-control variant-value variant1 touched"][#id="1"]

Selenium cannot find element even after giving a high implicitly waiting time

Im trying to automize some webpages and run into the following error:
I have passed the login screen, which gives no problems, but after being redirected to the next page, python gives the following error:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element:
I have tried to fix it by introducing the driver.implicitly.wait, the time.sleep and the WebDriverWait(driver, time).until(EC.presence_of_element_located((By.ID, "myDynamicElement")) functions, but all the options do not seem to work.
I have shown the relevant HTML code below:
<input type="Text" class="urEdf2TxtEnbl" autocomplete="off" id="DLG_VARIABLE_vsc_CommonVariablesList_VAR_5_VARINPUT_inp" ct="I" name="DLG_VARIABLE_vsc_CommonVariablesList_VAR_5_VARINPUT_inp" st="" tp="STRING" value="502309" onchange="sapUrMapi_InputField_change('DLG_VARIABLE_vsc_CommonVariablesList_VAR_5_VARINPUT_inp',event);" onblur="sapUrMapi_InputField_Blur('DLG_VARIABLE_vsc_CommonVariablesList_VAR_5_VARINPUT_inp',event);" onkeydown="sapUrMapi_InputField_keydown('DLG_VARIABLE_vsc_CommonVariablesList_VAR_5_VARINPUT_inp',event);" onkeyup="sapUrMapi_InputField_KeyUp('DLG_VARIABLE_vsc_CommonVariablesList_VAR_5_VARINPUT_inp',event);" onfocus="sapUrMapi_InputField_focus('DLG_VARIABLE_vsc_CommonVariablesList_VAR_5_VARINPUT_inp',event);" onselectstart="sapUrMapi_InputField_onselectstart('DLG_VARIABLE_vsc_CommonVariablesList_VAR_5_VARINPUT_inp',event);">
The HTML code in the region around this is shown below:
<input type="Text" class="urEdf2TxtEnbl" autocomplete="off" id="DLG_VARIABLE_vsc_CommonVariablesList_VAR_4_VARINPUT_inp" ct="I" name="DLG_VARIABLE_vsc_CommonVariablesList_VAR_4_VARINPUT_inp" st="" tp="STRING" value="" onchange="sapUrMapi_InputField_change('DLG_VARIABLE_vsc_CommonVariablesList_VAR_4_VARINPUT_inp',event);" onblur="sapUrMapi_InputField_Blur('DLG_VARIABLE_vsc_CommonVariablesList_VAR_4_VARINPUT_inp',event);" onkeydown="sapUrMapi_InputField_keydown('DLG_VARIABLE_vsc_CommonVariablesList_VAR_4_VARINPUT_inp',event);" onkeyup="sapUrMapi_InputField_KeyUp('DLG_VARIABLE_vsc_CommonVariablesList_VAR_4_VARINPUT_inp',event);" onfocus="sapUrMapi_InputField_focus('DLG_VARIABLE_vsc_CommonVariablesList_VAR_4_VARINPUT_inp',event);" onselectstart="sapUrMapi_InputField_onselectstart('DLG_VARIABLE_vsc_CommonVariablesList_VAR_4_VARINPUT_inp',event);">
What I am trying to do is to change the value: value="502309". See below for the full code:
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.get('xxxx')
login = driver.find_element_by_xpath('xxx')
login.send_keys('xxx')
passw = driver.find_element_by_xpath('xxx')
passw.send_keys('xxx')
button = driver.find_element_by_xpath('xxx')
button.click()
driver.maximize_window()
driver.implicitly_wait(120)
mat = driver.find_element_by_id('DLG_VARIABLE_vsc_CommonVariablesList_VAR_2_VARINPUT_inp')
driver.close()
Try to print the html using beautifulsoup so you can check if the element really exist. For your reference on how to use it, see link
I don't know if this will help but i had the same problem and solved it by this:
searchbox = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located(
(By.XPATH, "your_xpath_here")
The above code shows that the webdriver will wait's for an element located in your page.
Issue with your code is not wait , but rather correct element locator. As far as I can see from limited HTML DOM you have provided, part of name and id of element you want to locate inside variable mat is changing. You can locate your element using below code ( Also i have included more sophisticated way to wait for element load).
mat = WebDriverWait(driver, 120).until(EC.presence_of_element_located((By.XPATH, "//input[starts-with(#id,'DLG_VARIABLE_vsc_CommonVariablesList_VAR')]")))

Python Selenium find element by xpath or by id issue

I am trying to enter text into a text box on a web page but I am unable to locate it. I've tried finding it by xpath using the placeholder but may have had the wrong syntax as it was throwing an error.
The error I get with the below python is element not interactable - but it's a text field? surely it's intractable?
HTML:
<div class="name-filter-input"> == $0
<input placeholder="Search" ng-model="filter"
class="ng-pristine ng-valid">
</div>
My Python:
browser.find_element_by_class_name('name-filter-input')
campaign_text_field = browser.find_element_by_class_name('name-filter-input')
campaign_text_field.send_keys(x)
It seems you are trying to interact with the division instead of the input field.
Could you try changing the class name as so:
campaign_text_field = browser.find_element_by_class_name('ng-pristine ng-valid')
Use CSS Selector for the input element.
campaign_text_field = browser.find_element_by_css_selector('input.ng-pristine.ng-valid')
campaign_text_field.send_keys("XXX")
For the best practice induce WebDriverWait() and wait for element_to_be_clickable()
WebDriverWait(browser,20).until(EC.element_to_be_clickable((By.CSS_SELECTOR,'input.ng-pristine.ng-valid'))).send_keys("XXX")
Add following libraries.
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

Selenium, select based on "onclick" value

With Selenium, I'm trying to find the following checkbox on webpage.
<input type="checkbox" value="1" onclick=" document.getElementById('lastCheminClicked').value='123'; createInputsBinaireCell(25,'colonne5',1,0789,1,1,0,this.checked, this);">
The distinctive part is the '123' value in the "onclick", this is what selenium should look for.
Any way to find it on page? I have tried with xpath with no sucess.
As you mentioned the partial value 123 is distinct within the onclick event so to locate the element you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input[type='checkbox'][onclick*='123']")))
Using XPATH:
element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[#type='checkbox' and contains(#onclick,'123')]")))
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
XPath selectors allow using contains() function which can be used for partial match on the attribute or text value of the DOM element.
The relevant selector would be something like:
//input[contains(#onlclick, '123')]
Demo:
More information:
XPath Tutorial
XPath Axes
XPath Operators & Functions
You might try finding all input tags, and then iterate through each looking at the onclick attribute. For example:
from selenium.webdriver.common.by import By
input_tags = driver.find_elements(By.TAG_NAME, 'input')
found_tag = None
for input_tag in input_tags:
onclick_attribute = input_tag.get_attribute('onclick')
if ".value='123'" in onclick_attribute:
found_tag = input_tag
break
You'll probably need exception handling around the get_attribute call.

Categories