======= Selenium ======= Nos bajamos la imagen de selenium con los drivers de chrome y de firefox: Chrome: http://chromedriver.chromium.org/downloads docker run -ti iwanttobefreak/selenium Entramos en modo interactivo para probarlo: ipython Python 2.7.13 (default, Sep 26 2018, 18:42:22) Type "copyright", "credits" or "license" for more information. IPython 5.1.0 -- An enhanced Interactive Python. ? -> Introduction and overview of IPython's features. %quickref -> Quick reference. help -> Python's own help system. object? -> Details about 'object', use 'object??' for extra details. In [1]: Ahora podemos lanzar comandos: from selenium import webdriver from selenium.webdriver.firefox.options import Options options = Options() options.add_argument("--headless") driver = webdriver.Firefox(options=options) Por ejemplo vamos a buscar un tren en la web de Renfe: url = 'http://www.renfe.com' driver.get(url) Y grabamos la url en un fichero: driver.save_screenshot('/tmp/selenium/renfe.png') Ejemplo headless chrome con timeout en llamada get from selenium import webdriver from selenium.webdriver.firefox.options import Options options = Options() options.add_argument("--headless") url1 = 'http://10.255.255.1' url1_timeout = 5 driver = webdriver.Firefox(firefox_options = options) driver.set_page_load_timeout(url1_timeout) driver.get(url1) Ejemplo headless chrome con timeout en llamada get from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.support import expected_conditions as EC options = Options() options.add_argument('--headless') options.add_argument('--no-sandbox') options.add_argument('--disable-dev-shm-usage') url1 = 'http://10.255.255.1' url1_timeout = 5 driver = webdriver.Chrome(desired_capabilities = options.to_capabilities()) driver.set_page_load_timeout(url1_timeout) driver.get(url1) ====== Python firefox remote headless ====== Por definición siempre que es remote es headless from selenium.webdriver import Firefox, FirefoxProfile, Remote host = '172.30.10.18' port = '4444' host = selenium_hub_host port = selenium_hub_port url = f'{host}:{port}/wd/hub' d = Remote(command_executor = url, desired_capabilities = desired_capabilities) # MUY importante para evitar error: # selenium.common.exceptions.ElementClickInterceptedException: Message: Element is not clickable at point (179,16) because another element obscures it d.set_window_size(1920, 1080) ====== Python firefox remote ====== 1. Arrancar el standalone version: '3.7' services: hub: container_name: hub image: selenium/standalone-firefox 2. Obtner la IP de ese contenedor 3. Probar from selenium import webdriver host = "192.168.3.44" port = "4444" desired_capabilities = { 'browserName': 'firefox', 'javascriptEnabled': True, } self.driver = webdriver.Remote(command_executor = host + ':' + port + '/wd/hub', desired_capabilities = desired_capabilities) ====== Python chrome headless local ====== **IMPORTANTE**: si no se especifica el tamaño de la pantalla puede no encontrar objetos en el DOM. Ejemplo: https://www.linkedin.com/search/results/companies/?keywords=autoescuela&origin=SWITCH_SEARCH_VERTICAL' from selenium import webdriver from selenium.webdriver.chrome.options import Options CHROMEDRIVER_PATH = '/usr/local/bin/chromedriver' options = Options() options.add_argument('--headless') options.add_argument("window-size=1920,1080") driver = webdriver.Chrome(CHROMEDRIVER_PATH, chrome_options=options) ====== Python firefox headless local ====== ===== Sin profile ===== **IMPORTANTE**: si no se especifica el tamaño de la pantalla puede no encontrar objetos en el DOM. Ejemplo: https://www.linkedin.com/search/results/companies/?keywords=autoescuela&origin=SWITCH_SEARCH_VERTICAL' from selenium.webdriver.firefox.options import Options from selenium.webdriver import Firefox # Local headless options = Options() options.headless = True driver = Firefox(options = options) ===== Con profile ===== from selenium.webdriver.firefox.options import Options from selenium.webdriver import Firefox, FirefoxProfile # Local headless options = Options() options.headless = True driver = Firefox(firefox_profile = profile, options = options) ====== Python firefox headless local con profile y options ====== https://stackoverflow.com/a/52898225/11436137 from selenium import webdriver; from selenium.webdriver.firefox.options import Options cProfile = webdriver.FirefoxProfile(); dwnd_path = os.getcwd(); cProfile.add_preference('browser.download.folderList', '2'); cProfile.add_preference('browser.download.manager.showWhenStarting', 'false'); cProfile.add_preference('browser.download.dir', 'dwnd_path'); cProfile.add_preference('browser.helperApps.neverAsk.saveToDisk', 'application/octet-stream,application/vnd.ms-excel'); options = Options() options.headless = True driver = webdriver.Firefox(firefox_profile=cProfile, firefox_options=options, executable_path=r'C:\path\to\geckodriver.exe') ====== Errores ====== ===== selenium.common.exceptions.ElementClickInterceptedException: Message: Element is not clickable at point (179,16) because another element obscures it ===== **Causa**: se ha iniciado un webdriver remoto sin especificar las dimensiones de la ventana **Solución**: driver.set_window_size(1920, 1080) ===== selenium.common.exceptions.WebDriverException: Message: Failed to decode response from marionette ===== **Causa**: * Se ha especificado un tamaño de ventana con set_window_size() (probablemente es irrelevante) * Se ha quedado sin memoria la instancia de Firefox **Solución**: especificar variable "shm_size". Ejemplo docker-compose: easyredmine-backup-selenium: container_name: easyredmine-backup-selenium image: selenium/standalone-firefox #restart: unless-stopped # Mandatory, to avoid "Message: Failed to decode response from marionette" error shm_size: ${SHM_SIZE} #environment: # - START_XVFB=False networks: network-easyredmine-backup: aliases: - easyredmine-backup-selenium volumes: - ${DOCKER_HOST_DOWNLOAD_DIR}:${DOCKER_CONTAINER_DOWNLOAD_DIR} ====== PROXY ====== Para firefox: webdriver.DesiredCapabilities.FIREFOX['proxy']\\ Para chrome: webdriver.DesiredCapabilities.CHROME['proxy'] from selenium import webdriver from selenium.webdriver.firefox.options import Options from selenium.webdriver.common.proxy import * PROXY = "172.17.0.1:3128" webdriver.DesiredCapabilities.FIREFOX['proxy'] = { "httpProxy":PROXY, "ftpProxy":PROXY, "sslProxy":PROXY, "proxyType":"MANUAL" } options = Options() options.add_argument("--headless") driver = webdriver.Firefox(options=options) ====== Sesiones ====== ===== Firefox ===== Abrimos firefox en local. Escribimos en la barra **about:profiles**. Creamos un nuevo pofile y le asignamos un directorio. Lanzamos el profile y navegamos para que nos guarde información, por ejemplo el login de whatsapp. Lanzamos selenium con la siguiente propiedad: myprofile = webdriver.FirefoxProfile("") driver = webdriver.Firefox(myprofile) ===== Chrome ===== Simplemente le tenemos que indicar un directorio y ya lo graba ahí. Funciona con Chromedriver 70 a 73. Lo podemos descargar de:\\ https://chromedriver.storage.googleapis.com/index.html from selenium import webdriver from selenium.webdriver.chrome.options import Options CHROMEDRIVER_PATH = '/chromedriver70/chromedriver' options = Options() options.add_argument('user-data-dir=/selenium/session') options.add_argument("window-size=1920,1080") driver = webdriver.Chrome(CHROMEDRIVER_PATH, options=options) ====== Whatsapp ====== ===== Enviar mensaje ===== xpath = './/span[contains(@title, "Armando Bronca")]' o = driver.find_element_by_xpath(xpath) o.click() xpath = './/div[contains(@class, "_3u328 copyable-text selectable-text")]' o = driver.find_element_by_xpath(xpath) o.send_keys('Mensaje enviado desde selenium') xpath = './/button[contains(@class, "_3M-N-")]' o = driver.find_element_by_xpath(xpath) o.click() ===== Adjuntar fichero ===== xpath = './/span[contains(@title, "Armando Bronca")]' o = driver.find_element_by_xpath(xpath) o.click() xpath = './/div[contains(@title, "Adjuntar")]' o = driver.find_element_by_xpath(xpath) o.click() o = driver.find_element_by_xpath("//input[@type='file']") o.send_keys(os.getcwd()+"/tmp/caron.png") xpath = './/span[contains(@data-icon, "send-light")]' o = driver.find_element_by_xpath(xpath) o.click() ====== Padres e hijos ====== Tenemos el siguiente código:
{{:informatica:linux:padres_hijos.png|}} Queremos hacer click en el checkbox, que es un campo input (la caja verde), pero es dinámico y no tiene el identificador. El indentificador está dentro del div que tiene el texto en title que es la caja padre en rojo {{:informatica:linux:padres_hijos2.png|}} Primero seleccionamos el bloque padre, buscando por div y title que queramos: menu_click='NULL' menu_click='AMA DE CASA' menu_click='CUENTA AJENA FIJO' xpath='//div[@title="' + menu_click + '"]' padre = driver.find_element_by_xpath(xpath) Ahora dentro de esa caja, selecctionamos el input para hacer click xpath2='.//input[@type="checkbox"]' hijo = padre.find_element_by_xpath(xpath2) hijo.click() Si a partir de un elemento queremos seleccionar el padre:\\ Seleccionamos el elemento: xpath='//label[text()="AMA DE CASA"]' obj = driver.find_element_by_xpath(xpath) Y a partir de ese elemento el padre: padre=obj.find_element_by_xpath("./..") ====== Grabar el contenido de la web en un archivo ====== ===== Texto ===== https://stackoverflow.com/a/50420667/2695864 En mi caso fue muy útil porque no fui capaz, ni con chrome ni con firefox, de obtener el xpath de un popup que al hacer click en cualquier parte se cerraba. html = driver.execute_script("return document.body.innerHTML;") with open("login.html","w") as f: f.write(html) ===== Captura de pantalla ===== fichero = f"{datetime.datetime.now():%Y%m%d_%H%M%S}" driver.set_window_size(1080,1800) driver.save_screenshot("captura.png") driver.save_screenshot("captura_" + fichero + ".png")