Es importante diferenciar entre dos cattegorías de elemetnos de subida:
- Elementos basados en la etiqueta HTML
input. - Elementos implementados mediante tecnologías como JavaScript o Flash, donde no se utiliza
input.
- Subida mediante etiquetas input
Cuando el control es un input, se puede emplear el método send_keys de Selenium directamente. Ejemplo ilustrativo:
from selenium import webdriver as wd
import time
nav = wd.Firefox()
nav.get('http://sitio-ejemplo.com/upload')
campo = nav.find_element_by_id('archivo')
campo.send_keys('D:\\datos\\imagen.jpg')
- Subida mediante elementos no input
Para elementos que no son input, se requiere interactuar con los cuadros de diálogo del sistema operativo. Selenium no controla estos diálogos nativamente, por lo que se recurrre a bibliotecas auxiliares.
Opciones habituales:
pywin32para manipulación de ventanas en Windows.pywinautopara automatización de aplicaciones de escritorio.pyautoguipara simulación de eventos de teclado y ratón.AutoItpara creación de scripts dedicados al manejo de diálogos.
Uso de pywin32
Instalación: pip install pywin32. Implementación:
from selenium import webdriver as wd
import win32gui
import win32con
nav = wd.Firefox()
nav.get('http://sitio-ejemplo.com/upload')
nav.find_element_by_css_selector('#btn-subir').click()
# Localizar la ventana de diálogo
ventana = win32gui.FindWindow('#32770', 'Cargar archivo')
cb_ex = win32gui.FindWindowEx(ventana, 0, 'ComboBoxEx32', None)
cb = win32gui.FindWindowEx(cb_ex, 0, 'ComboBox', None)
entrada = win32gui.FindWindowEx(cb, 0, 'Edit', None)
boton = win32gui.FindWindowEx(ventana, 0, 'Button', None)
# Ingresar ruta y confirmar
win32gui.SendMessage(entrada, win32con.WM_SETTEXT, None, 'D:\\videos\\clip.wmv')
win32gui.SendMessage(ventana, win32con.WM_COMMAND, 1, boton)
Uso de pywinauto
Instalación: pip install pywinauto. Ejemplo:
from selenium import webdriver as wd
from pywinauto import Desktop
import time
nav = wd.Chrome()
nav.get('http://sitio-ejemplo.com/upload')
nav.maximize_window()
time.sleep(1)
escritorio = Desktop()
dlg = escritorio['Abrir']
dlg["Edit"].type_keys("D:\\documentos\\archivo.txt")
dlg["Button"].click()
Uso de pyautogui
Caso básico:
from selenium import webdriver as wd
import pyautogui
import time
nav = wd.Chrome()
nav.get('http://sitio-ejemplo.com/upload')
nav.maximize_window()
nav.find_element_by_name('file').click()
time.sleep(1)
pyautogui.write(r'D:\\backups\\data.zip')
time.sleep(1)
pyautogui.press('enter')
Para rutas con caracteres especiales, se combina con pyperclip:
from selenium import webdriver as wd
import pyautogui
import pyperclip
import time
nav = wd.Chrome()
nav.get('http://sitio-ejemplo.com/upload')
nav.maximize_window()
nav.find_element_by_name('file').click()
pyperclip.copy(r'D:\\proyectos\\diseño gráfico.psd')
time.sleep(1)
pyautogui.hotkey('ctrl', 'v')
time.sleep(1)
pyautogui.press('enter')
Uso de AutoIt
Script AutoIt para manejo de diálogos:
ControlFocus("Cargar archivo", "", "Edit1")
WinWait("[CLASS:#32770]", "", 10)
ControlSetText("Cargar archivo", "", "Edit1", $CmdLine[1])
Sleep(2000)
ControlClick("Cargar archivo", "", "Button1")
Compilar el script a ejecutable (subir.exe) e invocarlo desde Python:
from selenium import webdriver as wd
import os
import time
nav = wd.Firefox()
nav.get('http://sitio-ejemplo.com/upload')
nav.find_element_by_id('upload-btn').click()
time.sleep(1)
os.system('D:\\herramientas\\subir.exe "D:\\archivos\\reporte.pdf"')
time.sleep(3)
nav.quit()
Los títulos de los diálogos varían por navegador: en Firefox suele ser 'Cargar archivo', en Chrome 'Abrir', y en Internet Explorer 'Seleccionar archivo para cargar'.
Subida de múltiples archivos
Para cargar varios archivos, se especifican las rutas encerradas entre comillas y separadas por espacios en el campo de entrada, como: "D:\\doc1.txt" "D:\\doc2.txt". Todos los archivos deben residir en la misma ubicación.