0

Background:

I have the following HTML code that I am trying to get a XPATH to use with Selenium

<div class="btn-group">
<a type="button" class="btn btn-primary btn-user" onclick="AiD('182030801')" href="/download.pdf?id=182030801&amp;h=917901e6659ad5eb53970aecf687b53e&amp;u=cache&amp;ext=pdf" target="_blank" style="border-top-left-radius: 3px;border-bottom-left-radius: 3px;">
<i class="fas fa-cloud-download-alt" aria-hidden="true" style="margin-right: 9px;margin-left: 2px;font-size: 25px;vertical-align: middle;color: #119802;"></i>Download ( PDF )
</a>
[...]
</div>

Code:

What have I tried to do with Python's Selenium is the following, however I cannot quiet get it to work without Python throwing an error:

browser.find_element(By.XPATH, "//div[@class='btn-group']/a").click()
browser.find_element(By.XPATH, "//div[@class='btn tn-primary btn-user']").click()

Error:

When I run the above snippet of code, the following error is produced and script crashes thereafter:

selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//div[@class='btn tn-primary btn-user']"}

Problem:

The error states "no such element", however the element clearly exists "class="btn btn-primary btn-user""

Question:

How can I use Seleniums XPATH to "see" class="btn btn-primary btn-user" and click it to download a PDF?

Link:

PDFDrive

3kstc
  • 1,871
  • 3
  • 29
  • 53

3 Answers3

1

USe Xpath //div/a[@class='btn btn-primary btn-user']

  1. Make sure the intended element is not under an iFrame. If it is then first you need to switch into that iFrame and then have to perform the action

  2. Make sure you are using proper synchrnization and your element is ready. Introduce explicit wait as below:

    driver.get('https://www.pdfdrive.com/querying-xml-xquery-xpath-and-sqlxml-in-context-d38665640.html')
    WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//div[@class='btn-group']/a"))).click()
    time.sleep(10) // it doesn't recommanded to put hardcoded wait but for debugging purpose you can check 
    

    Import below packages for this:

     from selenium.webdriver.support import expected_conditions as EC
     from selenium.webdriver.common.by import By
     from selenium.webdriver.support.wait import WebDriverWait
    
NarendraR
  • 7,577
  • 10
  • 44
  • 82
  • No errors with the code, however the download doesn't get triggered :/ – 3kstc Sep 30 '20 at 05:58
  • @3kstc, Updated the answer. check with wait condition. its working at my end. let me know if still you are facing same issue – NarendraR Sep 30 '20 at 06:07
  • Yeah, my code also works on my end so it might be something else. – Arundeep Chohan Sep 30 '20 at 06:09
  • @3kstc, PDF getting download. but if you perform some action just after download it shifted the focus. To test whether file downloading or not try to put `time.sleep(10)` just after the download click command – NarendraR Sep 30 '20 at 06:13
  • I can't seem to make it work - probably best if you have the full python script here - so I can compare the differences.. – 3kstc Sep 30 '20 at 06:17
  • @3kstc, I've updated the answer. please refer the latest – NarendraR Sep 30 '20 at 06:17
  • Thanks, the sleep did do some good - the question now is how do I make the code "Sleep" until the download is complete with selenium? – 3kstc Sep 30 '20 at 06:20
  • @3kstc, Unfortunately there is not direct way to do that. But still you can refer this work around https://stackoverflow.com/a/62319275/5097027 – NarendraR Sep 30 '20 at 06:25
  • Last question: How does one obtain the filename that was just downloaded? – 3kstc Sep 30 '20 at 06:28
  • I believe `Querying XML_ XQuery, XPath, and SQL_XML in Context ( PDFDrive ).pdf` this is the file name of your download file. Try to download it manually and check the name. Its not dynamic so should be fine for now – NarendraR Sep 30 '20 at 06:33
0

You are using "div" tag but I can see respective class = btn btn-primary btn-user is inside "a" tag

try below code :

browser.find_element(By.XPATH, "//a[@class='btn tn-primary btn-user']").click()

Or you can go with another locator as well.

CSS : a.btn.btn-primarybtn-user
Ankur Singh
  • 1,239
  • 1
  • 8
  • 18
0

So you need to wait for the element to be clickable. Triggered the download.

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait 
from selenium.webdriver.support import expected_conditions as EC

options = Options()
driver = webdriver.Chrome(ChromeDriverManager().install(),options=options)
url = 'https://www.pdfdrive.com/querying-xml-xquery-xpath-and-sqlxml-in-context-d38665640.html'

driver.get(url)
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,'a.btn.btn-primary.btn-user'))).click()
Arundeep Chohan
  • 9,779
  • 5
  • 15
  • 32