0

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>&nbsp;אקסל
                </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>&nbsp;אפשרויות
                  </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>&nbsp;יצא סידור לאקסל</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

1
  • Add the error message you are getting? Commented Nov 19, 2020 at 11:39

2 Answers 2

1

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

Sign up to request clarification or add additional context in comments.

4 Comments

I've tried and received the following error: " selenium.common.exceptions.TimeoutException: Message: " Without any further details
When I remove the headless chrome option it downloads the file. What can be the reason for that?
@nomno : For headless browser you need to specify window-size. chrome_options = webdriver.ChromeOptions() chrome_options.add_argument('--headless') chrome_options.add_argument('window-size=1920x1080');
Thanks KunduK! adding chrome_options.add_argument('window-size=1920x1080') seems to solve the problem.
1

To click on the ng-click element you can use either of the following Locator Strategies:

  • Using css_selector:

    driver.find_element_by_css_selector("button.btn.btn-success.btn-block[ng-click^='excelRota']>i.fa.fa-file-excel-o.fa-lg").click()
    
  • Using xpath:

    driver.find_element_by_xpath("//button[@class='btn btn-success btn-block' and starts-with(@ng-click, 'excelRota')][contains(., 'אקסל')]").click()
    


Ideally, as the element is an Angular element, to click on the element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following Locator Strategies:

  • Using CSS_SELECTOR:

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.btn.btn-success.btn-block[ng-click^='excelRota']>i.fa.fa-file-excel-o.fa-lg"))).click()
    
  • Using XPATH:

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[@class='btn btn-success btn-block' and starts-with(@ng-click, 'excelRota')][contains(., 'אקסל')]"))).click()
    
  • Note: You have to add the following imports :

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

Comments

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.