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
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"))
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)
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))
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