I'm trying to insert the variable "i" on my Xpath but I'm hitting a wall.
This is my code:
for i in range(len(results_nbr)):
xpath = "//*[#id='w1']/div["
xpath += int(i)
xpath += "]/div/div[2]/h3"
elem = driver.find_element_by_xpath(xpath)
elem.click()
time.sleep(1)
I'm using selenium and it works fine if I have the variable in the code as below:
elem = driver.find_element_by_xpath('//*[#id="w1"]/div[1]/div/div[2]/h3')
What is wrong with my code please? I tried int(i) and str(i) with same result.
I appreciate your help. Thanks
First point: use string formatting. There are a lot of available options in Python:
- xpath = '//*[#id="w1"]/div[%s]/div/div[2]/h3' % i
- xpath = '//*[#id="w1"]/div[{}]/div/div[2]/h3'.format(i)
- xpath = f'//*[#id="w1"]/div[{i}]/div/div[2]/h3' # in Python 3.6 and later
Second point: in XPath indexing starts from 1. So div[0] won't work. Try
for i in range(1, len(results_nbr) + 1):
...
Related
I am working on web automation with selenium and I need to find an element with the xpath. This by itself is not a problem but the code needs to run multiple times and when it does that the HTML xpath changes. This is also not a problem. I have used simple math to get the new xpath every time.
The xpathes look like this
1. run: '//*[#id="input-text-3"]'
2. run: '//*[#id="input-text-5"]'
3. run: '//*[#id="input-text-7"]' etc.
I solved this problem using this code:
y = 1
#Corme browser already defined and on website
while True:
mathop1 = y*2 + 1
xxpath = ""'//*[#id="input-text-' + str(mathop1) + '"]'""
xxpath1 = "'" + str(xxpath) + "'"
print(xxpath1)
Bezeichnung = driver.find_element_by_xpath(xxpath1)
Bezeichnung.send_keys(file1name)
y = y + 1
What this does is that every time the program loops it updates y so the xpath will be correct. I tried using the output from xxpath1 to find the element like you normally would and it works fine however as soon as I use the variable it does not work. Specifically, the problem is this I can't use the variable.
Bezeichnung = driver.find_element_by_xpath(xxpath1)
why does this not work?
First of all, I guess you have to put a wait condition there.
Also, I do not understand why are you using so much strings inside string and converting string to string again, so I removed that
y = 1
#Corme browser already defined and on website
while True:
mathop1 = y*2 + 1
xxpath = '//*[#id="input-text-{}"]'.format(mathop1)
Bezeichnung = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, xxpath)))
Bezeichnung.send_keys(file1name)
y = y + 1
The address below is the xpath address.
//label[#for="check54490"])
The check box is checked when typed as below.
driver.find_element_by_xpath('//label[#for="check54490"]').click()
However, there are many check boxes that need to be checked, so I am going to make variables and check them.
I made a variable as below, but an error occurs.
umber = [54490]
for num in umber:
elem = f'//label[#for="check{num}"]'
elm2 = f"'{elem}'"
xpath = elem2
driver.find_element_by_xpath(xpath).click()
the error message is as follows.
Is the approach good or is it impossible in the first place?
Please give me some advice.
selenium.common.exceptions.InvalidSelectorException: Message: invalid selector: Unable to locate an element with the xpath expression driver.find_element_by_xpath('//label[#for="check1000054759"]').click() because of the following error:
SyntaxError: Failed to execute 'evaluate' on 'Document': The string 'driver.find_element_by_xpath('//label[#for="check54490"]').click()' is not a valid XPath expression.
(Session info: chrome=90.0.4430.85)
Instead of doing it in for loop you can directly do it in the xpath for single value as below -
driver.find_element_by_xpath("//label[#for='check" + str(umber[0]) + "']")
Now since you have asked how you can do it in case of multiple values consider the following code example -
umber = [54490, 54490]
for num in umber:
driver.find_element_by_xpath("//label[#for='check" + str(num) + "']").click()
OR you can have each number in different variable -
xbuttonNum = '54490'
ybuttonNum = '54491'
zbuttonNum = '54521'
driver.find_element_by_xpath("//label[#for='check" + xbuttonNum + "']").click()
driver.find_element_by_xpath("//label[#for='check" + ybuttonNum + "']").click()
driver.find_element_by_xpath("//label[#for='check" + zbuttonNum + "']").click()
Alternatively you can customize your xpath unique for all the elements and iterate over them all at once like -
AllElementwithCheckString = driver.find_elements_by_xpath("//label[starts-with(#for,'check')]")
for elem in AllElementwithCheckString:
elem.click()
I'm trying to workout the number of for loops to run depending on the number of List (totalListNum)
And it seems that it is returning Nonetype when infact it should be returning either text or int
website:https://stamprally.org/?search_keywords=&search_keywords_operator=and&search_cat1=68&search_cat2=0
Code Below
for prefectureValue in prefectureValueStorage:
driver.get(
f"https://stamprally.org/?search_keywords&search_keywords_operator=and&search_cat1={prefectureValue}&search_cat2=0")
# Calculate How Many Times To Run Page Loop
totalListNum = driver.find_element_by_css_selector(
'div.page_navi2.clearfix>p').get_attribute('text')
totalListNum.text.split("件中")
if totalListNum[0] % 10 != 0:
pageLoopCount = math.ceil(totalListNum[0])
else:
continue
currentpage = 0
while currentpage < pageLoopCount:
currentpage += 1
print(currentpage)
I dont think you should use get_attribute. Instead try this.
totalListNum = driver.find_element_by_css_selector('div.page_navi2.clearfix>p').text
First, your locator is not unique
Use this:
div.page_navi2.clearfix:nth-of-type(1)>p
or for the second element:
div.page_navi2.clearfix:nth-of-type(2)>p
Second, as already mentioned, use .text to get the text.
If .text does not work you can use .get_attribute('innerHTML')
Relatively new in programming, doing Python with Selenium and Xpath
this is from this website:https://www.marketbeat.com/stocks/NASDAQ/AMZN/earnings/
what I am trying to do is copy the dates of the past earnings.
Problem is it is in the table and it also has tag.
I have this full Xpath:
/html/body/div[1]/main/article/form/div[8]/div[2]/div[2]/div/div[5]/div/table/tbody/tr[2]/td[1]
and upon inspection it shows this
< td data-sort-value="20201027000000">10/27/2020 < / td >
I am trying to get the 10/27/2020 out from here but I don't know how to.
It is easy when it is just the < td >$1.53< /td > where just giving the full xpath and then doing a .text on it gives me the text.
point is how do I get 10/27/2020. I would suspect that I would have to go over data-sort-value="" part.
Here is what I have :
stringeEPSxpath = """/html/body/div[1]/main/article/form/div[8]/div[2]/div[2]/div/div[5]/div/table/tbody/tr[""" + row + """]/td[1]"""
Date = stringeEPSxpath.text
(the row part is just me iterating the website page through a loop no problem there.)
For the rest of my code it has been pretty simple :
stringeEPSxpath = """/html/body/div[1]/main/article/form/div[8]/div[2]/div[2]/div/div[5]/div/table/tbody/tr[""" + row + """]/td[3]"""
stringEPSxpath = """/html/body/div[1]/main/article/form/div[8]/div[2]/div[2]/div/div[5]/div/table/tbody/tr[""" + row + """]/td[4]"""
elem = driver.find_element_by_xpath(stringeEPSxpath)
elem2 = driver.find_element_by_xpath(stringEPSxpath)
fix1 = (elem.text).replace(')','')
fix2 = (elem2.text).replace(')','')
eps1 = fix1.replace('(','-')
eps2 = fix2.replace('(','-')
As you can see above all I had to do was set a variable to it then use .text to convert it to a string. But now that does not work for dates.
The end result is the error of AttributeError: 'str' object has no attribute 'text' which I would suspect is because of the data-sort-value="20201027000000" part.
In this code stringeEPSxpath is string, not WebElement.
stringeEPSxpath = """/html/body/div[1]/main/article/form/div[8]/div[2]/div[2]/div/div[5]/div/table/tbody/tr[""" + row + """]/td[1]"""
Date = stringeEPSxpath.text
You can try this one:
from selenium.webdriver.common.by import By
element = driver.find_element(By.XPATH,"//td[#data-sort-value='20201027000000']")
Date = element.text
Forgot driver.find_element_by_xpath(stringeEPSxpath) which actually uses xpath. Since I copy and pasted from my other program I guess I deleted too much and completely forgot to add in the driver.findxpath.
Instead of writing 10+ IF statements, I'm trying to create one IF statement using a variable. Unfortunately, I'm not familiar with how to implement string concatenation for xpath using python. Can anyone teach me how to perform string formatting for the following code segments?
I would greatly appreciate it, thanks.
if page_number == 1:
next_link = browser.find_element_by_xpath('//*[#title="Go to page 2"]')
next_link.click()
page_number = page_number + 1
time.sleep(30)
elif page_number == 2:
next_link = browser.find_element_by_xpath('//*[#title="Go to page 3"]')
next_link.click()
page_number = page_number + 1
time.sleep(30)
This answer is not about string concatenation, but about simple problem solution...
Instead of clicking particular link on pagination you can click "Next" button:
pages_number = 10
for _ in range(pages_number):
driver.find_element_by_xpath("//a[#title='Go to next page']").click()
time.sleep(30)
If you need to open specific page you can use below:
required_page = 3
driver.find_element_by_link_text(required_page).click()
P.S. I assumed you are talking about this site
You can use a for-loop
Ex:
for i in range(1, 10):
next_link = browser.find_element_by_xpath('//*[#title="Go to page {0}"]'.format(str(i+1))) #using str.format for page number
next_link.click()
time.sleep(30)