2

I've written a script in python with selenium to click on a certain link in a webpage to download an excel file. However, when I execute my script, it throws timeout exception. How can I make it work? Any help will be greatly appreciated.

Link to the site: webpage

Script I've tried with:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
wait = WebDriverWait(driver, 10)
driver.get('replace_with_above_link')

item = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".hasmore #dlink")))
item.click()
driver.quit()

Html elements which contain the dropdown options:

<li class="hasmore drophover"><span>Share &amp; more</span><div><ul><li><button class="tooltip" tip="Use a customizable report creator that can<br>output HTML, CSV, or a shareable link." id="share_on_ajax_result_table">Modify &amp; Share Table</button></li><li><button class="tooltip" tip="Get a bit of widget code to emed this table on your site">Embed this Table</button></li><li><button class="tooltip" tip="Convert the table below to comma-separated values<br>suitable for use with excel">Get as Excel Workbook (experimental)</button><a id="dlink" style="display: none;"></a></li><li><button class="tooltip" tip="Export table as <br>suitable for use with excel">Get table as CSV (for Excel)</button></li><li><button class="tooltip" tip="">Strip Mobile Formatting</button></li><li><a id="a_ajax_result_table" name="ajax_result_table" href="#ajax_result_table::none">Copy Link to Table to Clipboard</a></li><li><button class="tooltip" tip="">About Sharing Tools</button></li><li><button class="tooltip" tip=""><a href="https://www.youtube.com/watch?v=MWapXbaWs_U&amp;feature=youtu.be" target="_blank">Video: SR Sharing Tools &amp; How-to</a></button></li><li><button class="tooltip" tip=""><a href="https://www.youtube.com/watch?v=JkDLV0roT14&amp;feature=youtu.be" target="_blank">Video: Stats Table Tips &amp; Tricks</a></button></li></ul></div></li>

Location of that file in that webpage (the desired link is marked with pencil): enter image description here

5
  • Did u try to first move the cursor over to the "Share&more" element? Commented Mar 30, 2018 at 20:44
  • Yes. I even clicked on the share&more link in the first place and found it working. Troubles come up when i try to initiate a click on the link I mentioned above. Commented Mar 30, 2018 at 20:52
  • The link actually results in file download and a SaveAs dialog. Set proper options for Chrome for automatic downlading (like here for example stackoverflow.com/questions/49053624/…) Commented Mar 30, 2018 at 21:22
  • Possible duplicate of How to download any file and save it to the desired location using Selenium Webdriver Commented Mar 30, 2018 at 23:01
  • 1
    @SiKing, I went through your profile to see if you always mark different questions as duplicate which have been asked before? The answer is no. You try to solve them when you see you may be able to do so. However, take a look at this link. That is your latest reply. Do you think that the linked question was unique? You tried to solve that because it was easy but when you come across any post like what I've posted here, you mark it as duplicate. What a joke!!!!! Commented Mar 31, 2018 at 2:14

2 Answers 2

1

Target link is hidden and so wait for its visibility will always fail. You should try to handle button node instead:

item = wait.until(EC.visibility_of_element_located((By.XPATH, "//li[span='Share & more']")))
item.click()
wait.until(lambda driver: "drophover" in item.get_attribute("class"))
item.find_element_by_xpath("//button[.='Get as Excel Workbook (experimental)']").click()
Sign up to request clarification or add additional context in comments.

10 Comments

I tried it just now. It throws timeout exception when it hits the line containing wait.until(). Hope you take a look. Given plus one for this. Thanks sir.
Do you mean this line item = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".hasmore")))?
Nope sir. This line wait.until(lambda driver: "drophover" in item.get_attribute("class")).
Yep. My mistake :) That's because ".hasmore" selector is unreliable (note that there are more than 1 node with "hasmore" class name). Try updated answer
Check this ticket and let me know in case it doesn't help
|
0

As you are trying to click on the link with text as Get as Excel Workbook (experimental) and as per your comment you are already able to click on the Share&more link in the first place and found it working next your intended <a> tagged element contains the attribute style set to display: none;. So to invoke click() to download you can use the following code block :

Get_as_Excel_Workbook_link = driver.find_element_by_xpath("//li[@class='hasmore drophover']//ul//li//a[@id='dlink']")
driver.execute_script("arguments[0].removeAttribute('style')", Get_as_Excel_Workbook_link)
Get_as_Excel_Workbook_link.click()

Update A

As per your comment :

comment

  • I am not sure if the xpath which you have used is a valid one or not :

    "//li[a[@id='dlink']]/a"
    
  • You tried using :

    Get_link = driver.find_element_by_xpath("//li[a[@id='dlink']]/a") 
    print(Get_link.get_attribute("outerHTML"))
    

But why? Is there any necessity?

  • As per my research and analysis you can be assured that you are at the right place. See the formatted version of the HTML you have shared and the resolution of the xpath I have provided.

<li class="hasmore drophover"><span>Share &amp; more</span>
  <div>
    <ul>
      <li><button class="tooltip" tip="Use a customizable report creator that can<br>output HTML, CSV, or a shareable link." id="share_on_ajax_result_table">Modify &amp; Share Table</button></li>
      <li><button class="tooltip" tip="Get a bit of widget code to emed this table on your site">Embed this Table</button></li>
      <li><button class="tooltip" tip="Convert the table below to comma-separated values<br>suitable for use with excel">Get as Excel Workbook (experimental)</button>
        <a id="dlink" style="display: none;"></a>
      </li>
      <li><button class="tooltip" tip="Export table as <br>suitable for use with excel">Get table as CSV (for Excel)</button></li>
      <li><button class="tooltip" tip="">Strip Mobile Formatting</button></li>
      <li><a id="a_ajax_result_table" name="ajax_result_table" href="#ajax_result_table::none">Copy Link to Table to Clipboard</a></li>
      <li><button class="tooltip" tip="">About Sharing Tools</button></li>
      <li><button class="tooltip" tip=""><a href="https://www.youtube.com/watch?v=MWapXbaWs_U&amp;feature=youtu.be" target="_blank">Video: SR Sharing Tools &amp; How-to</a></button></li>
      <li><button class="tooltip" tip=""><a href="https://www.youtube.com/watch?v=JkDLV0roT14&amp;feature=youtu.be" target="_blank">Video: Stats Table Tips &amp; Tricks</a></button></li>
    </ul>
  </div>
</li>

  • So the result you have seen is pretty correct. Now, for you understanding I have inserted some text as MyLink within the intended tag :

    <a id="dlink" style="display: none;"></a>
    
  • Converted as :

    <a id="dlink" style="display: none;">MyLink</a>
    
  • See the result :

result

  • Check out my solution once again I can ensure that works.

Update B

unable to locate element is good message to debug perhaps apart from "display: none;" you have pulled a rug over the actual issue by mentioning clicked on the share&more link in the first place and found it working. Troubles come up when i try to initiate a click on the link.

If you observe the HTML the element is within class="tooltip" so you need to induce a waiter as follows :

//perform click on the link Share&more
Get_as_Excel_Workbook_link = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//li[@class='hasmore drophover']//ul//li//a[@id='dlink']")))
driver.execute_script("arguments[0].removeAttribute('style')", Get_as_Excel_Workbook_link)
Get_as_Excel_Workbook_link.click()

5 Comments

Thanks a lot for your solution @DebanjanB. It looks promising. As soon as I'm near my pc I'm gonna let you know the feedback.
I tried it just now but unfortunately it could not do the trick. To be specific I tried using Get_link = driver.find_element_by_xpath("//li[a[@id='dlink']]/a") print(Get_link.get_attribute("outerHTML")) as well to see if I'm in the right place. The result it produces is <a id="dlink" style="display: none;"></a>. Turn out that there is no such link to be clicked.
@Topto Check out my answer update and let me know the status.
I tried with your suggested portion several times. Every time it throws unable to locate element error. However, I tried your xpath //li[@class='hasmore drophover']//ul//li//a[@id='dlink'] in the chrome console as well to see if it is able to locate the desired portion. But it could not. Then finally I tried with this //li[contains(@class,'hasmore')]//ul//li//a[@id='dlink'] in the chrome and found it locating the desired portion. When I tried the same within the script then I encounter element not visible error. This is the total status.
Check out my answer update and let me know the status.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.