I am trying to automate a website with selenium to download an excel file. I have the following HTML for the button:
<div class="row ng-scope" ng-if="!model.update_rota"> <div class="col-sm-12 hidden-xs hidden-sm"> <button type="button" class="btn btn-success btn-block" title="יצא לאקסל" ng-click="excelRota();" ng-disabled="!model.rota.id || model.rotaLoading"> <i class="fa fa-file-excel-o fa-lg"></i> אקסל </button> </div> <!-- ngIf: model.features.reports.attributes.availability_shifts_report.value == 'True' --> <!-- ngIf: model.features.tips.is_active && model.features.tips.attributes.tips_calculate.value == 'True' --> <div class="col-sm-12"> <div class="btn-group btn-block visible-xs-block visible-sm-block"> <button type="button" class="btn btn-info btn-block dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" ng-disabled="model.rotaLoading"> <i class="fa fa-bars fa-lg"></i> אפשרויות </button> <ul class="dropdown-menu"> <!-- ngIf: model.features.tips.is_active && model.features.tips.attributes.tips_calculate.value == 'True' --> <li ng-class="{'disabled': !model.rota.id}" class="" style=""><a href="#" ng-click="excelRota();"><i class="fa fa-file-excel-o text-success"></i> יצא סידור לאקסל</a></li> <!-- ngIf: model.features.reports.attributes.availability_shifts_report.value == 'True' --> </ul> </div> </div> </div>
I have tried clicking on the button with the following find element by class:
driver.find_element_by_class_name('btn btn-success btn-block').click()
The error message I get is:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":".btn btn-success btn-block"}
I have also tried:
driver.execute_script("excelRota();")
And received the following error:
selenium.common.exceptions.JavascriptException: Message: javascript error: excelRota is not defined
I have logged in this website successfully and worked my way around the site up until the excel file page, but I can’t figure out how to click this button.
I have written my script as headless chrome if it makes any difference.
Update:
This is my whole code:
from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By import os import time import pandas as pd from tkinter import * import datetime excel_shifts_download_url = 'https://app.shiftorganizer.com/excel/rota/125102/?' download_dir = "C:\Users\Documents\Python Scripts\projects\shifts_script" driver_path = "C:\Users\Documents\Python Scripts\projects\shifts_script\chromedriver.exe" shiftorgnizer_login_url = 'https://app.shiftorganizer.com/login/?lang=he&previous=homepage&greeting=true' # enabling headless chrome def setting_chrome_options(): chrome_options = Options() chrome_options.add_argument("--headless") chrome_options.add_argument('--no-sandbox') chrome_options.add_argument('--disable-gpu') chrome_options.add_argument('--disable-software-rasterizer') return chrome_options driver = webdriver.Chrome(executable_path=driver_path, options=setting_chrome_options()) # Login GUI def login_gui(): root = Tk() root.title('Shifter') root.geometry("250x130") root.focus_force() global entry_company_id global entry_username global entry_password global checkbox_var checkbox_var = IntVar() # Text near text box username & password label_company_id = Label(root, text='Company ID') label_username = Label(root, text='Username') label_password = Label(root, text='Password') # Textbox for username & password entry_company_id = Entry(root) entry_username = Entry(root) entry_password = Entry(root) # Positioning of text label_company_id.grid(row=0, sticky=E) label_username.grid(row=1, sticky=E) label_password.grid(row=2, sticky=E) # Positioning of textboxes entry_company_id.grid(row=0, column=1) entry_username.grid(row=1, column=1) entry_password.grid(row=2, column=1) # Login button root.bind('<Return>', site_login) b = Button(root, text='Login', command=site_login) b.grid(row=4, column=1) checkbox = Checkbutton(root, text='Get next week Shifts', variable=checkbox_var) checkbox.grid(row=3, column=1) root.mainloop() current_day_date = datetime.date.today() next_sunday_date = current_day_date + datetime.timedelta( (6 - current_day_date.weekday()) % 7 ) # Site login with user's credentials def site_login(): global company_id global username global password username = str(entry_username.get()) password = str(entry_password.get()) company_id = str(entry_company_id.get()) driver.get (shiftorgnizer_login_url) driver.implicitly_wait(20) driver.find_element_by_id('company').send_keys(company_id) driver.find_element_by_id ('username').send_keys(username) driver.find_element_by_id ('password').send_keys(password) driver.find_element_by_id('log-in').click() # downloading shifts file enable_download(driver) WebDriverWait(driver, 10).until(EC.title_contains("בית | ShiftOrganizer")) driver.get('https://app.shiftorganizer.com/app/rota') WebDriverWait(driver, 10).until(EC.title_contains("סידור | ShiftOrganizer")) WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,".btn.btn-success.btn-block"))).click() # if checkbox_var.get() == 0: # driver.find_element_by_class_name('col-sm-12 hidden-xs hidden-sm').click() # elif checkbox_var.get() == 1: # driver.get('https://app.shiftorganizer.com/app/rota'+'?date='+next_sunday_date) # WebDriverWait(driver, 10).until(EC.title_contains("סידור | ShiftOrganizer")) # driver.get(excel_shifts_download_url) isFileDownloaded() # permission to download file via Selenium def enable_download(driver): driver.command_executor._commands["send_command"] = ("POST", '/session/$sessionId/chromium/send_command') params = {'cmd':'Page.setDownloadBehavior', 'params': {'behavior': 'allow', 'downloadPath': download_dir}} driver.execute("send_command", params) # check if file has been downloaded def isFileDownloaded(): file_path = download_dir+"\schedule.xlsx" while not os.path.exists(file_path): time.sleep(1) if os.path.isfile(file_path): print("File Downloaded Successfully") login_gui()
When I disable headless chrome option the file is being downloaded
Advertisement
Answer
find_element_by_class_name()
doesn’t accepts multiple class name. Instead you can use css selector
.
To avoid synchronization issue Induce WebDriverWait()
and wait for element_to_be_clickable()
and following css selector.
WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,".btn.btn-success.btn-block"))).click()
You need to import below libraries.
from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait
Reference link for css selector