web-dev-qa-db-fra.com

Selenium donne le nom du fichier lors du téléchargement

Je travaille avec un script Selenium où j'essaie de télécharger un fichier Excel et de lui donner un nom spécifique. Voici mon code:

Existe-t-il de toute façon un nom spécifique pour le fichier en cours de téléchargement?

Code:

#!/usr/bin/python
from Selenium import webdriver
from Selenium.webdriver.firefox.firefox_profile import FirefoxProfile

profile = FirefoxProfile()
profile.set_preference("browser.helperApps.neverAsk.saveToDisk", "text/plain, application/vnd.ms-Excel, text/csv, text/comma-separated-values, application/octet-stream")
profile.set_preference("browser.download.dir", "C:\\Downloads" )
browser = webdriver.Firefox(firefox_profile=profile)

browser.get('https://test.com/')
browser.find_element_by_partial_link_text("Excel").click() # Download file
15
user3580316

Vous ne pouvez pas spécifier le nom du fichier téléchargé via Selenium. Cependant, vous pouvez télécharger le fichier, rechercher le dernier fichier dans le dossier téléchargé et renommer comme vous le souhaitez.

Remarque: les méthodes empruntées aux recherches Google peuvent contenir des erreurs. mais vous avez l'idée.

import os
import shutil
filename = max([Initial_path + "\\" + f for f in os.listdir(Initial_path)],key=os.path.getctime)
shutil.move(filename,os.path.join(Initial_path,r"newfilename.ext"))
10
parishodak

Il y a quelque chose que je corrigerais pour la réponse @parishodak:

le nom de fichier ici ne renverra que le chemin relatif (ici le nom du fichier) et non le chemin absolu.

C'est pourquoi @FreshRamen a obtenu l'erreur suivante après:

File "/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/‌​python2.7/genericpath.py", 
line 72, in getctime return os.stat(filename).st_ctime OSError: 
[Errno 2] No such file or directory: '.localized'

Il y a le bon code:

import os
import shutil

filepath = 'c:\downloads'
filename = max([filepath +"\"+ f for f in os.listdir(filepath)], key=os.path.getctime)
shutil.move(os.path.join(dirpath,filename),newfilename)
5
toshiro92

J'espère que cet extrait n'est pas si déroutant. Il m'a fallu un certain temps pour créer ceci et est vraiment utile, car il n'y a pas eu de réponse claire à ce problème, avec juste cette bibliothèque.

import os
import time
def tiny_file_rename(newname, folder_of_download):
    filename = max([f for f in os.listdir(folder_of_download)], key=lambda xa :   os.path.getctime(os.path.join(folder_of_download,xa)))
    if '.part' in filename:
        time.sleep(1)
        os.rename(os.path.join(folder_of_download, filename), os.path.join(folder_of_download, newname))
    else:
        os.rename(os.path.join(folder_of_download, filename),os.path.join(folder_of_download,newname))

J'espère que cela sauve la journée de quelqu'un, bravo.

EDIT: Merci à @Om Prakash d'éditer mon code, cela m'a fait me souvenir que je n'ai pas expliqué le code de manière réfléchie.

L'utilisation de la fonction max([]) peut conduire à une condition de concurrence critique, vous laissant avec un fichier vide ou corrompu (je le sais par expérience). Vous voulez vérifier si le fichier est complètement téléchargé en premier lieu. Cela est dû au fait que Selenium n'attend pas que le téléchargement du fichier se termine, donc lorsque vous recherchez le dernier fichier créé, un fichier incomplet apparaîtra dans votre liste générée et essaiera de déplacer ce fichier. Et même alors, vous feriez mieux d'attendre un peu que le fichier soit libre de Firefox.

EDIT 2: Plus de code

On m'a demandé si 1 seconde suffisait et surtout c'est le cas, mais au cas où vous auriez besoin d'attendre plus que cela, vous pourriez changer le code ci-dessus en ceci:

import os
import time
def tiny_file_rename(newname, folder_of_download, time_to_wait=60):
    time_counter = 0
    filename = max([f for f in os.listdir(folder_of_download)], key=lambda xa :   os.path.getctime(os.path.join(folder_of_download,xa)))
    while '.part' in filename:
        time.sleep(1)
        time_counter += 1
        if time_counter > time_to_wait:
            raise Exception('Waited too long for file to download')
    filename = max([f for f in os.listdir(folder_of_download)], key=lambda xa :   os.path.getctime(os.path.join(folder_of_download,xa)))
    os.rename(os.path.join(folder_of_download, filename), os.path.join(folder_of_download, newname))
4
dmb

Voici une autre solution simple, où vous pouvez attendre la fin du téléchargement, puis obtenir le nom du fichier téléchargé à partir de chrome téléchargements.

Chrome:

# method to get the downloaded file name
def getDownLoadedFileName(waitTime):
    driver.execute_script("window.open()")
    # switch to new tab
    driver.switch_to.window(driver.window_handles[-1])
    # navigate to chrome downloads
    driver.get('chrome://downloads')
    # define the endTime
    endTime = time.time()+waitTime
    while True:
        try:
            # get downloaded percentage
            downloadPercentage = driver.execute_script(
                "return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('#progress').value")
            # check if downloadPercentage is 100 (otherwise the script will keep waiting)
            if downloadPercentage == 100:
                # return the file name once the download is completed
                return driver.execute_script("return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('div#content  #file-link').text")
        except:
            pass
        time.sleep(1)
        if time.time() > endTime:
            break

Firefox:

def getDownLoadedFileName(waitTime):
    driver.execute_script("window.open()")
    WebDriverWait(driver,10).until(EC.new_window_is_opened)
    driver.switch_to.window(driver.window_handles[-1])
    driver.get("about:downloads")

    endTime = time.time()+waitTime
    while True:
        try:
            fileName = driver.execute_script("return document.querySelector('#contentAreaDownloadsView .downloadMainArea .downloadContainer description:nth-of-type(1)').value")
            if fileName:
                return fileName
        except:
            pass
        time.sleep(1)
        if time.time() > endTime:
            break

Une fois que vous avez cliqué sur le lien/bouton de téléchargement, il vous suffit d'appeler la méthode ci-dessus.

 # click on download link
 browser.find_element_by_partial_link_text("Excel").click()
 # get the downloaded file name
 latestDownloadedFileName = getDownLoadedFileName(180) #waiting 3 minutes to complete the download
 print(latestDownloadedFileName)

Java + Chrome:

Voici la méthode en Java.

public String waitUntilDonwloadCompleted(WebDriver driver) throws InterruptedException {
      // Store the current window handle
      String mainWindow = driver.getWindowHandle();

      // open a new tab
      JavascriptExecutor js = (JavascriptExecutor)driver;
      js.executeScript("window.open()");
     // switch to new tab
    // Switch to new window opened
      for(String winHandle : driver.getWindowHandles()){
          driver.switchTo().window(winHandle);
      }
     // navigate to chrome downloads
      driver.get("chrome://downloads");

      JavascriptExecutor js1 = (JavascriptExecutor)driver;
      // wait until the file is downloaded
      Long percentage = (long) 0;
      while ( percentage!= 100) {
          try {
              percentage = (Long) js1.executeScript("return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('#progress').value");
              //System.out.println(percentage);
          }catch (Exception e) {
            // Nothing to do just wait
        }
          Thread.sleep(1000);
      }
     // get the latest downloaded file name
      String fileName = (String) js1.executeScript("return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('div#content #file-link').text");
     // get the latest downloaded file url
      String sourceURL = (String) js1.executeScript("return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('div#content #file-link').href");
      // file downloaded location
      String donwloadedAt = (String) js1.executeScript("return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('div.is-active.focus-row-active #file-icon-wrapper img').src");
      System.out.println("Download deatils");
      System.out.println("File Name :-" + fileName);
      System.out.println("Donwloaded path :- " + donwloadedAt);
      System.out.println("Downloaded from url :- " + sourceURL);
     // print the details
      System.out.println(fileName);
      System.out.println(sourceURL);
     // close the downloads tab2
      driver.close();
     // switch back to main window
      driver.switchTo().window(mainWindow);
      return fileName;
  }

Voici comment appeler cela dans votre script Java.

// download triggering step 
downloadExe.click();
// now waituntil download finish and then get file name
System.out.println(waitUntilDonwloadCompleted(driver));

Sortie:

Télécharger les deatils

Nom du fichier: -RubyMine-2019.1.2 (7) .exe

Chemin d'accès téléchargé: - chrome: //fileicon/C%3A%5CUsers%5Csupputuri%5CDownloads%5CRubyMine-2019.1.2%20 (7) .exe? Scale = 1.25x

Téléchargé depuis l'URL: - https://download-cf.jetbrains.com/Ruby/RubyMine-2019.1.2.exe

RubyMine-2019.1.2 (7) .exe

4
supputuri