python - Selenium da el nombre del archivo al descargar
file download (5)
Aquí hay otra solución simple, donde puede esperar hasta que se complete la descarga y luego obtener el nombre del archivo descargado de las descargas de Chrome.
Cromo:
# 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
Una vez que haga clic en el enlace / botón de descarga, simplemente llame al método anterior.
# 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:
Aquí está el método 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;
}
Así es como llamar a esto en su script java.
// download triggering step
downloadExe.click();
// now waituntil download finish and then get file name
System.out.println(waitUntilDonwloadCompleted(driver));
Salida:
Descargar detalles
Nombre de archivo: -RubyMine-2019.1.2 (7) .exe
Ruta descargada: - Chrome: //fileicon/C%3A%5CUsers%5Csupputuri%5CDownloads%5CRubyMine-2019.1.2%20 (7) .exe? Scale = 1.25x
Descargado desde url: - https://download-cf.jetbrains.com/ruby/RubyMine-2019.1.2.exe
RubyMine-2019.1.2 (7) .exe
Estoy trabajando con un script de selenio donde estoy tratando de descargar un archivo de Excel y darle un nombre específico. Este es mi código:
¿Hay alguna forma de darle un nombre específico al archivo que se está descargando?
Código:
#!/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
Espero que este fragmento no sea tan confuso. Me tomó un tiempo crear esto y es realmente útil, porque no ha habido una respuesta clara a este problema, solo con esta biblioteca.
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))
Espero que esto salve el día de alguien, saludos.
EDITAR: Gracias a @Om Prakash que editó mi código, me hizo recordar que no expliqué el código sin embargo.
El uso de la función
max([])
podría provocar una condición de carrera, dejándolo con un archivo vacío o dañado (lo sé por experiencia).
En primer lugar, desea verificar si el archivo está completamente descargado.
Esto se debe al hecho de que el selenio no espera a que se complete la descarga del archivo, por lo que cuando verifique el último archivo creado, aparecerá un archivo incompleto en su lista generada e intentará mover ese archivo.
E incluso entonces, es mejor esperar un poco para que el archivo esté libre de Firefox.
EDIT 2: más código
Me preguntaron si 1 segundo era suficiente y, sobre todo, lo es, pero en caso de que necesite esperar más de eso, puede cambiar el código anterior a esto:
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))
Hay algo que corregiría para la respuesta de @parishodak:
el nombre de archivo aquí solo devolverá la ruta relativa (aquí el nombre del archivo), no la ruta absoluta.
Es por eso que @FreshRamen recibió el siguiente error despué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''
Existe el código correcto:
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)
No puede especificar el nombre del archivo de descarga a través de selenio. Sin embargo, puede descargar el archivo, encontrar el último archivo en la carpeta descargada y cambiar el nombre como desee.
Nota: los métodos prestados de las búsquedas de Google pueden tener errores. Pero se entiende la idea.
import os
import shutil
filename = max([f for f in os.listdir(''c:/downloads'')], key=os.path.getctime)
shutil.move(os.path.join(dirpath,filename),newfilename)
Puede descargar el archivo y nombrarlo al mismo tiempo usando
urlretrieve
:
import urllib
url = browser.find_element_by_partial_link_text("Excel").get_attribute(''href'')
urllib.urlretrieve(url, "/choose/your/file_name.xlsx")