iterated click on href link list - python

I want to iterate through href links and click on each one. My problem is that I cannot extract href, because it is not help me, when I click it i get an empty page. I should click directly on list of buttons.
There are total 21 nodes, hrefList consist of 21 items.
Here is example of html :
<div class="inner25">
כרטיס רופא >
</div>
<div class="inner25">
כרטיס רופא >
</div>
My code is :
hrefList = driver.find_elements_by_xpath(".//a[contains(text(), 'כרטיס רופא')]")
for link in hrefList:
link.click()
The link of site is :https://www.ida.org.il/?pageType=19&langId=1&paramIds=%2Con_321%2Con_322%2Con_354%2Con_355%2Con_320&scope=&parameterSearch=
In every square you see the doctor. i want to click on each of them.
I found that loop open first link and then failed. What can be a problem?
I tried also this code:
for href in range(1,3):
hrefList[href].click()
First link it open, and then failed.
This is an error :
File "C:\Program Files\Python36\lib\site-packages\selenium\webdriver\remote\webelement.py", line 78, in click
self._execute(Command.CLICK_ELEMENT)
File "C:\Program Files\Python36\lib\site-packages\selenium\webdriver\remote\webelement.py", line 499, in _execute
return self._parent.execute(command, params)
File "C:\Program Files\Python36\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 297, in execute
self.error_handler.check_response(response)
File "C:\Program Files\Python36\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 194, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
(Session info: chrome=60.0.3112.113)
(Driver info: chromedriver=2.32.498550 (9dec58e66c31bcc53a9ce3c7226f0c1c5810906a),platform=Windows NT 10.0.15063 x86_64)

Use this xapth it returns 21 nodes of your website
//a[contains(#href, 'https://www.ida.org.il/?categoryId=96318&itemId')]
This code in Java. You have to come back to main page and locate element
public static void main(String[] args) {
String URL="https://www.ida.org.il/?pageType=19&langId=1&paramIds=%2Con_321%2Con_322%2Con_354%2Con_355%2Con_320&scope=&parameterSearch=";
WebDriver driver=new FirefoxDriver();
driver.get(URL);
List<WebElement> links=driver.findElements(By.xpath("//a[contains(#href, 'https://www.ida.org.il/?categoryId=96318&itemId')]"));
System.out.println("Total links: "+links.size());
for (int i=0;i<links.size();i++) {
links.get(i).click();
System.out.println(i+"Current URL is: "+driver.getCurrentUrl());
driver.navigate().back();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
links=driver.findElements(By.xpath("//a[contains(#href, 'https://www.ida.org.il/?categoryId=96318&itemId')]"));
}
driver.close();
}

Beginner issue.You can find a lot of questions related to stale element exception.
You should never do actions that are changing the page in a loop using a list of already found objects, else you will get stale element since the element is not attached to the DOM.
You should save all hrefs values in a list, then in your loop you should do the find element based on the saved href value and call click on the found element.
If the page changes/reloads you need to find the element again.

Related

Python/Selenium button click on class does not work

<fieldset class = "A">
::before
<button class = "ButtonA" type ="submit">
::before
Click Me
</button>
::after
</fieldset>
I am trying to open a page and click a button on the page. However, no matter what function call I make it throws the same message telling my the class does not exist, however, I'm positive it does. I don't see it nested in a iFrame. So what am I not understanding here, also why does it throw a error for a css selector if I am looking for an html class.
I get the following error
File "C:\Python38\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 564, in find_element_by_class_name
return self.find_element(by=By.CLASS_NAME, value=name)`
File "C:\Python38\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 976, in find_element
return self.execute(Command.FIND_ELEMENT, { `
File "C:\Python38\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 321, in execute
self.error_handler.check_response(response)`
File "C:\Python38\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response`
raise exception_class(message, screen, stacktrace)selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":".ButtonA"}`
driver.get("https://www.websiteWithButton.com")
#ensure html is loaded
driver.implicitly_wait(10)
#check for iFrame
#driver.switch_to.frame('PossibleiFrame')
#ButtonA is a a class that exists, I'm positive.
button = driver.find_element_by_class_name('ButtonA')
button.click()
I just give my entire solution.Base on your step
driver.get("https://www.websiteWithButton.com")
#ensure html is loaded
driver.implicitly_wait(10)
#check for iFrame
#driver.switch_to.frame('PossibleiFrame')
#ButtonA is a a class that exists, I'm positive.
button_list = driver.find_elements_by_tag('button')
for i, x in enumerate(button_list):
print(f'Index: {i}')
x.click() # you can find the index of ButtonA you want by click them step by step
After you get the index of ButtonA, just click it directly
button_list[index].click().
the index reflect the position of ButtonA in page source, as long as page source unchange, you can access it.
This might not be a smart way, but at least you can find button element you want as long as you are in correct page.

Message: element not interactable Error While Sending Keys [search_bar.send_keys(course_name)] To Search Bar Of Youtube using selenium python

I tried Most of the solution of StackOverflow but didn't work for me
I am trying to send some course name to youtube search bar using selenium python it works fine before but now it gives this error while doing this
And search_bar.send_keys(course_name) works fine for other websites but not in YT
Traceback (most recent call last):
File "src/gevent/greenlet.py", line 766, in gevent._greenlet.Greenlet.run
File "/home/sh4d0w/PycharmProjects/AutoMate/venv/lib/python3.7/site-packages/eel/__init__.py", line 257, in _process_message
return_val = _exposed_functions[message['name']](*message['args'])
File "/home/sh4d0w/PycharmProjects/AutoMate/SmallTalk.py", line 72, in SingleQueryinputValue
RecommendCourse.getUdacityCourse(str(val))
File "/home/sh4d0w/PycharmProjects/AutoMate/RecommendCourse.py", line 160, in getUdacityCourse
getYoutubeCourse(course_name, driver)
File "/home/sh4d0w/PycharmProjects/AutoMate/RecommendCourse.py", line 98, in getYoutubeCourse
search_bar.send_keys(course_name)
File "/home/sh4d0w/PycharmProjects/AutoMate/venv/lib/python3.7/site-packages/selenium/webdriver/remote/webelement.py", line 479, in send_keys
'value': keys_to_typing(value)})
File "/home/sh4d0w/PycharmProjects/AutoMate/venv/lib/python3.7/site-packages/selenium/webdriver/remote/webelement.py", line 633, in _execute
return self._parent.execute(command, params)
File "/home/sh4d0w/PycharmProjects/AutoMate/venv/lib/python3.7/site-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
self.error_handler.check_response(response)
File "/home/sh4d0w/PycharmProjects/AutoMate/venv/lib/python3.7/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable
(Session info: chrome=81.0.4044.129)
2020-04-29T08:00:02Z <Greenlet at 0x7fd2089c67b8: _process_message({'call': 2.1877049007713376, 'name': 'SingleQueryi, <geventwebsocket.websocket.WebSocket object at 0x7)> failed with ElementNotInteractableException
Code sample
option = webdriver.ChromeOptions()
option.add_argument("window-size=1200x600");
driver = webdriver.Chrome('/usr/bin/chromedriver', options=option)
driver.get("https://www.youtube.com")
getYoutubeCourse(course_name, driver)
getYoutubeCourse() function body
def getYoutubeCourse(course_name, driver):
time.sleep(2)
search_bar = driver.find_element_by_xpath('//*[#id="search"]')
search_bar.send_keys(course_name)
search_bar_button = WebDriverWait(driver, 5).until(EC.element_to_be_clickable(
(By.XPATH, '//*[#id="search-icon-legacy"]')))
search_bar_button.click()
......
then after this, the logic of scraping the youtube links is there
I also tried web driver wait and all, and my drivers are also up to date
Please help I am new in python and selenium
There is 3 elements found by xpath : //*[#id="search"]
You have to correct it to
//input[#id="search"]
I also got the same problem. After hours filled with agony I finally found a solution.
While copying xpath (or any another id you are using to refer it) it points out to the entire search box container. After repeated trials and observations I found that a particular element (of the webpage which you can view in developer) with input mentioned was the one to be looked for:
<input id="search" autocapitalize="none" autocomplete="off" autocorrect="off" name="search_query" tabindex="0" type="text" spellcheck="false" placeholder="Search" aria-label="Search" aria-haspopup="false" role="combobox" aria-autocomplete="list" dir="ltr" class="ytd-searchbox" style="outline: none;">
The problem while copying xpath is that you get id of the container.
So use 'copy full xpath'. This will refer to the particular element within the container which can be given input.
full xpath for the input element of search box is:
'/html/body/ytd-app/div/div/ytd-masthead/div[3]/div[2]/ytd-searchbox/form/div/div[1]/input'
You can use it like:
search_bar = driver.find_element_by_xpath('/html/body/ytd-app/div/div/ytd-masthead/div[3]/div[2]/ytd-searchbox/form/div/div[1]/input')
search_bar.send_keys(song_name)
time.sleep(1)#You can skip this.
search_bar.send_keys(Keys.ENTER)
P.S. Excuse the terminology. I am also a beginner and this is my first answer.
You can try this:
from selenium.webdriver.common.keys import Keys
def getYoutubeCourse(course_name, driver):
time.sleep(2)
search_bar = driver.find_element_by_xpath('//input[#id="search"]')
search_bar.send_keys(course_name)
time.sleep(1)
search_bar.send_keys(Keys.ENTER)
....
I'm the one who also got the same problem.
I tried full Xpath but it was still not working. And then, I plused [0] after xpath and it worked.
full xpath for the input element of search box is:
'/html/body/ytd-app/div/div/ytd-masthead/div[3]/div[2]/ytd-searchbox/form/div/div[1]/input[0]'
And this if full source code
chrome_driver = '/Users/Downloads/chromedriver'
driver = webdriver.Chrome(chrome_driver)
driver.get('https://www.youtube.com')
search_bar = driver.find_elements_by_xpath('/html/body/ytd-app/div/div/ytd-masthead/div[3]/div[2]/ytd-searchbox/form/div/div[1]/input')[0]
time.sleep(2)
search_bar.send_keys("black pink")
time.sleep(2)
search_bar.send_keys(Keys.RETURN)
Thank you

Python with Selenium Google Translate Error

I dont know where the problem is
I used theese sources
https://medium.com/python/python-selenium-mod%C3%BCl%C3%BC-kullan%C4%B1m%C4%B1-ders-1-36983185164c
https://www.youtube.com/watch?v=olOswIyeRlY
Code
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
driver_path = r"C:\Users\ruzgaricatsirketi\Desktop\chromedriver_win32\chromedriver.exe"
driver = webdriver.Chrome(executable_path=driver_path)
driver.get("https://translate.google.com/#tr/tr")
dinle = driver.find_element_by_id('gt-speech')
dinle.click()
time.sleep(2)
dinle.click()
time.sleep(3)
getir = driver.find_element_by_id('result_box').text
print(getir)
Error
DevTools listening on ws://127.0.0.1:12239/devtools/browser/76eb55d7-8aef-4b19-9d6e-fda8f4f1aee4
Traceback (most recent call last):
File "C:\Users\ruzgaricatsirketi\Desktop\test.py", line 13, in <module>
getir = driver.find_element_by_id('result_box').text
File "C:\Users\ruzgaricatsirketi\AppData\Local\Programs\Python\Python37-32\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 360, in find_element_by_id
return self.find_element(by=By.ID, value=id_)
File "C:\Users\ruzgaricatsirketi\AppData\Local\Programs\Python\Python37-32\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 978, in find_element
'value': value})['value']
File "C:\Users\ruzgaricatsirketi\AppData\Local\Programs\Python\Python37-32\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 321, in execute
self.error_handler.check_response(response)
File "C:\Users\ruzgaricatsirketi\AppData\Local\Programs\Python\Python37-32\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"id","selector":"result_box"}
(Session info: chrome=78.0.3904.97)
(Driver info: chromedriver=2.35.528161 (5b82f2d2aae0ca24b877009200ced9065a772e73),platform=Windows NT 10.0.18362 x86_64)
In order to work with Python correctly, it is crucial to learn to read the stack trace. In your case, these lines
File "C:\Users\ruzgaricatsirketi\Desktop\test.py", line 13, in <module>
getir = driver.find_element_by_id('result_box').text
say that the exception has its origin on line 13 in your file test.py, where you are trying to search for web element with id attribute set to value "result_box". Exception you have got is NoSuchElementException:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"id","selector":"result_box"}
As you can find in official documentation or many other places (and I bet there are thousands of them), this exception is raised when the element you are searching for is not found.
Try it yourself — open your tested Google Translator page and try to search for element with any existing id. E.g. on line 8 in your test file you are trying to locate element with id "gt-speech". Write document.getElementById("gt-speech") to your browsers console and whoala! It works, this node matches your search:
<div id="gt-speech" class="speech-button goog-toolbar-button"...>...</div>
Note especially the id="gt-speech" attribute, it is the one selenium will use to identify the object. However, if you try the same with id "result_box", you will get nothing (null is returned if using JS console to search for element), because there is no such element on the page (thus NoSuchElementException...).
My advice for you:
inspect the element you are trying to locate (on the most of the popular web browsers on Windows/Linux systems it is as easy as right-clicking the element and selecting the inspect option)
select some unique properties, you can use also other properties than id (preferably not inner text; IDs are best, but they are not always present...)
use those properties to find the element using selenium
And please, next time try to search a bit on your own before you ask, because this is some really really trivial problem you should be able to handle after first 5 minutes of any selenium course (in other words, UTFG :P)
EDIT
P.S. I can see you have got that invalid id from the video you have marked as your source. The fact that element with such id was present one year ago does not mean it will be there forever (an for every platform). If you need to get that certain element, you have to find another way how to define it using selenium locators I have mentioned earlier.

StaleElementReferenceException when trying to click on the links in a loop

Please click on the link below to see the link "BEAUTY" on which I am clicking
1. I am using this code to click on the "Beauty" link
driver = webdriver.Chrome("C:\\Users\\gaurav\\Desktop\\chromedriver_win32\\chromedriver.exe")
driver.maximize_window()
driver.get("http://shop.davidjones.com.au")
object = driver.find_elements_by_name('topCategory')
for ea in object:
print ea.text
if ea.text == 'Beauty':
ea.click()
I am getting the following exceptions after clickin on the link succesfully , can anybody tell me why I am getting it ?
Traceback (most recent call last):
File "C:/Users/gaurav/PycharmProjects/RIP_CURL/login_raw.py", line 10, in <module>
print ea.text
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webelement.py", line 73, in text
return self._execute(Command.GET_ELEMENT_TEXT)['value']
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webelement.py", line 493, in _execute
return self._parent.execute(command, params)
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 252, in execute
self.error_handler.check_response(response)
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 194, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
(Session info: chrome=63.0.3239.132)
(Driver info: chromedriver=2.34.522940 (1a76f96f66e3ca7b8e57d503b4dd3bccfba87af1),platform=Windows NT 6.2.9200 x86_64)
Try this:
from selenium import webdriver
print("bot started")
#chromeOptions = webdriver.ChromeOptions()
#driver = webdriver.Chrome(chrome_options=chromeOptions)
def specific_text(text, ea):
return str(text) == ea.text
driver = webdriver.Chrome("C:\\Users\\gaurav\\Desktop\\chromedriver_win32\\chromedriver.exe")
driver.maximize_window()
driver.get("http://shop.davidjones.com.au")
object_ = driver.find_elements_by_name('topCategory')
text_headers = [str(specific_text('Beauty', ea)) for ea in object_]
#print(text_headers)
index_text = text_headers.index("True")
#print(index_text)
object_[index_text].click()
You need to take care of certain factors as follows :
You have tried to create a List by the name object. object is a reserved built-in symbol in most of the Programming Languages. So as per Best Programming Practices we shouldn't use the name object.
The line print ea.text is badly indented. You need to add indentation.
Once you invoke click() on the WebElement with text as Beauty you need to break out of the loop.
Here is your own working code with some minor tweaks :
from selenium import webdriver
driver = webdriver.Chrome(executable_path=r'C:\path\to\chromedriver.exe')
driver.maximize_window()
driver.get("http://shop.davidjones.com.au")
object1 = driver.find_elements_by_name('topCategory')
for ea in object1:
print (ea.text)
if ea.text == 'Beauty':
ea.click()
break
Console Output :
Sale
Brands
Women
Men
Shoes
Bags & Accessories
Beauty
There's an easier way to do this. You can use an XPath that will specify the category name you want to click. That way you don't have to loop, it will find the desired element in one search.
//span[#name='topCategory'][.='Beauty']
I'm assuming you will be reusing this code. In cases like this, I would create a function that takes a string parameter which would be the category name that you want to click. You feed that parameter into the XPath above and you can then click any category on the page.
I tested this and it's working.

Python Selenium Stale Element Hangs Forever

I'm using Python Selenium to extract all links from a page and I chose Selenium because many of the sites I'm targeting use JS to render the DOM. However, Selenium is throwing a Stale Exception error when traversing the page <a> elements.
import from selenium.webdriver import Firefox
def request(url):
urls = []
browser = Firefox()
browser.implicitly_wait(7)
browser.get(url)
elements = browser.find_elements_by_xpath("//a")
for link in elements:
href = link.get_attribute('href')
urls.append(href)
browser.close()
return urls
This is the error selenium throws
File "/var/extractor/main.py", line 80, in request
href = link.get_attribute('href')
File "/usr/local/lib/python3.4/dist-packages/selenium/webdriver/remote/webelement.py", line 113, in get_attribute
resp = self._execute(Command.GET_ELEMENT_ATTRIBUTE, {'name': name})
File "/usr/local/lib/python3.4/dist-packages/selenium/webdriver/remote/webelement.py", line 469, in _execute
return self._parent.execute(command, params)
File "/usr/local/lib/python3.4/dist-packages/selenium/webdriver/remote/webdriver.py", line 201, in execute
self.error_handler.check_response(response)
File "/usr/local/lib/python3.4/dist-packages/selenium/webdriver/remote/errorhandler.py", line 194, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.StaleElementReferenceException: Message: Element not found in the cache - perhaps the page has changed since it was looked up
So to try to fix this I wrapped the get_attribute('href') in a try exception.
for link in elements:
try:
href = link.get_attribute('href')
except StaleElementReferenceException:
continue
urls.append(href)
But that didn't work either! The application never exits the for loop, it just hangs forever. So I'm not quite sure what to do. I've seen a lot of other posts regarding Stale Element Exception but none that hang forever. I feel like this whole StaleElement exception is a design flaw in selenium and it should be able to fail more gracefully then this. Would appreciate any suggestions on how to fix this.
[EDIT]: Until I figure this out, I'm sending the page_source to lxml to parse links instead of Selenium. This does solve this issue for now. But I'd prefer to not introduce another dependency and fix the issue with Selenium.

Categories