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.
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
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')
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):
...
Apologies, as I am a nascent coder...
Attempting to automate tasks (order processing) via selenium/chromedriver:
I am running into an issue. Since I don't understand what the problem is, I am having a difficult time fixing it.
I am attempting to get the text of an element, where that element is an item of a table. I know exactly where that data is, and modify the CSS selector string accordingly to get it.
No exceptions are being thrown, either by my code or by upstream code.
Here is the offending code:
rscSelector = '#ctl00_ctl00_contentMainPlaceHolder_MainContent_dlRSCName > tbody > tr > ' \
'td:nth-child({}) > table > tbody > tr:nth-child(1) > td > ' \
'span'.format(str(count+1)) # This element is 1 indexed, why? who knows
element = chrome.find_element_by_css_selector(rscSelector)
RSC = bD.RSCDict[element.text.strip()]
this is passed through a loop testing for a value in a field, then looking in a corresponding element to find the text I want. (two separate tables with corresponding information)
What is throwing me, is, the first 4 iterations, it works, 5 and up it fails to get the text. (passes '')
Furthermore, if I manually inspect the element in chrome, then it works... with no changes to the code, same runtime?
full block of code:
def accept_order2(order_R, quantity, chrome, chromeHandleID, firefox, fFoxHandleID):
chrome.switch_to.window(chromeHandleID)
chrome.switch_to.frame(chrome.find_element_by_css_selector('#itemDetail'))
RSC = None
for count in range(numberOfRSCs):
qtySelector = '#ctl00_ctl00_contentMainPlaceHolder_MainContent_rptCheckout_ctl00_' \
'datalstContainer_ctl{}_txtOrderQty'.format(str(count).rjust(2, '0')) # pad string/0 indexed
try:
element = chrome.find_element_by_css_selector(str(qtySelector))
except ElementNotVisibleException:
print('Double check at least 1 field has data entered into it.')
break
fieldQuantity = element.get_attribute("value")
if fieldQuantity != '' and fieldQuantity != ' ' and fieldQuantity is not None:
if int(fieldQuantity) == quantity:
rscSelector = '#ctl00_ctl00_contentMainPlaceHolder_MainContent_dlRSCName > tbody > tr > ' \
'td:nth-child({}) > table > tbody > tr:nth-child(1) > td > ' \
'span'.format(str(count+1)) # This element is 1 indexed, why? who knows
element = chrome.find_element_by_css_selector(rscSelector)
RSC = bD.RSCDict[element.text.strip()]
break
else:
raise ValueError('Origiinial Order Quantity and quantity supplied in field does not match')
This appears to be a bug in the chromedriver, however, I am well aware that I do not possess enough expertise to make such a claim.
Any help would profoundly be appreciated!!!
Christopher Lund
p.s. I am not in control of the webpage in which I am attempting to work with. and I am deliberately working with 2 browsers at the same time: firefox and Chrome. the Firefox code isn't shown for brevity sakes, as there are no issues there.
How I can know, that there is a text or not. I used this code:
pricelist = driver.find_elements_by_xpath(".//*[#id='scroll']/div[2]/div/div[2]/div")
if EC.text_to_be_present_in_element(By.XPATH(".//*[#id='scroll']/div[2]/div/div[2]/div[1]")):
price = pricelist[1].text
elif EC.text_to_be_present_in_element(By.XPATH(".//*[#id='scroll']/div[2]/div/div[2]/div[2]")):
price = pricelist[2].text
else:
price = pricelist[3].text
Problem:
TypeError: 'str' object is not callable
You can use Xpath to check length of text in the element. See code below.
price = driver.find_element_by_xpath(".//*[#id='scroll']/div[2]/div/div[2]/div[string-length(text()) > 1]").text
You can change the text length in xpath like /div[string-length(text()) > 10] to find an element which contains more than 10 characters.
By.XPATH is not a method, but simple string. Correct usage is
EC.text_to_be_present_in_element((By.XPATH, xpath_expression)))
If you want to match element that contains text, use [text()] predicate:
".//*[#id='scroll']/div[2]/div/div[2]/div[text()]"
I have used another method:
pricelist = driver.find_elements_by_xpath(".//*[#id='scroll']/div[%d]/div/div[2]/div" %num)
for prc in pricelist:
if len(prc.text) < 10 and len(prc.text) > 0:
price = prc.text
This method is slow enough, but the most readeable