[*]
robert w cazador
Así que estoy tratando de abrir sitios web en nuevas pestañas dentro de mi WebDriver. Quiero hacer esto, porque abrir un nuevo WebDriver para cada sitio web toma alrededor de 3.5 segundos usando PhantomJS, quiero más velocidad…
Estoy usando una secuencia de comandos de Python multiproceso y quiero obtener algunos elementos de cada página, por lo que el flujo de trabajo es así:
Open Browser
Loop throught my array
For element in array -> Open website in new tab -> do my business -> close it
Pero no puedo encontrar ninguna manera de lograr esto.
Aquí está el código que estoy usando. Se tarda una eternidad entre sitios web, necesito que sea rápido… Se permiten otras herramientas, pero no conozco demasiadas herramientas para desechar el contenido del sitio web que se carga con JavaScript (divs creados cuando se activa algún evento al cargar, etc.) Eso es por qué necesito Selenium… BeautifulSoup no se puede usar para algunas de mis páginas.
#!/usr/bin/env python
import multiprocessing, time, pika, json, traceback, logging, sys, os, itertools, urllib, urllib2, cStringIO, mysql.connector, shutil, hashlib, socket, urllib2, re
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from PIL import Image
from os import listdir
from os.path import isfile, join
from bs4 import BeautifulSoup
from pprint import pprint
def getPhantomData(parameters):
try:
# We create WebDriver
browser = webdriver.Firefox()
# Navigate to URL
browser.get(parameters['target_url'])
# Find all links by Selector
links = browser.find_elements_by_css_selector(parameters['selector'])
result = []
for link in links:
# Extract link attribute and append to our list
result.append(link.get_attribute(parameters['attribute']))
browser.close()
browser.quit()
return json.dumps({'data': result})
except Exception, err:
browser.close()
browser.quit()
print err
def callback(ch, method, properties, body):
parameters = json.loads(body)
message = getPhantomData(parameters)
if message['data']:
ch.basic_ack(delivery_tag=method.delivery_tag)
else:
ch.basic_reject(delivery_tag=method.delivery_tag, requeue=True)
def consume():
credentials = pika.PlainCredentials('invitado', 'invitado')
rabbit = pika.ConnectionParameters('localhost',5672,"https://stackoverflow.com/",credentials)
connection = pika.BlockingConnection(rabbit)
channel = connection.channel()
# Conectamos al canal
channel.queue_declare(queue="com.stuff.images", durable=True)
channel.basic_consume(callback,queue="com.stuff.images")
print ' [*] Waiting for messages. To exit press CTRL^C'
try:
channel.start_consuming()
except KeyboardInterrupt:
pass
workers = 5
pool = multiprocessing.Pool(processes=workers)
for i in xrange(0, workers):
pool.apply_async(consume)
try:
while True:
continue
except KeyboardInterrupt:
print ' [*] Exiting...'
pool.terminate()
pool.join()

aberna
Nota del editor: Esta respuesta ya no funciona para las nuevas versiones de Selenium. Consulte este comentario.
Puede lograr la apertura/cierre de una pestaña mediante la combinación de teclas MANDO + T o MANDO + W (OSX). En otros sistemas operativos puede usar CONTROL + T / CONTROL + W.
En selenium puedes emular tal comportamiento. Deberá crear un controlador web y tantas pestañas como las pruebas que necesite.
Aquí está el código.
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Firefox()
driver.get("http://www.google.com/")
#open tab
driver.find_element_by_tag_name('body').send_keys(Keys.COMMAND + 't')
# You can use (Keys.CONTROL + 't') on other OSs
# Load a page
driver.get('http://stackoverflow.com/')
# Make the tests...
# close the tab
# (Keys.CONTROL + 'w') on other OSs.
driver.find_element_by_tag_name('body').send_keys(Keys.COMMAND + 'w')
driver.close()
browser.execute_script('''window.open("http://bings.com","_blank");''')
Donde navegador es el controlador web
Este es un código común adaptado de otros ejemplos:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Firefox()
driver.get("http://www.google.com/")
#open tab
# ... take the code from the options below
# Load a page
driver.get('http://bings.com')
# Make the tests...
# close the tab
driver.quit()
las formas posibles eran:
-
Enviando <CTRL> + <T>
a un elemento
#open tab
driver.find_element_by_tag_name('body').send_keys(Keys.CONTROL + 't')
-
Enviando <CTRL> + <T>
a través de cadenas de acción
ActionChains(driver).key_down(Keys.CONTROL).send_keys('t').key_up(Keys.CONTROL).perform()
-
Ejecutar un fragmento de javascript
driver.execute_script('''window.open("http://bings.com","_blank");''')
Para lograr esto, debe asegurarse de que las preferencias browser.link.open_newwindow y browser.link.open_newwindow.restricción están correctamente configurados. Los valores predeterminados en las últimas versiones están bien, de lo contrario, supuestamente necesita:
fp = webdriver.FirefoxProfile()
fp.set_preference("browser.link.open_newwindow", 3)
fp.set_preference("browser.link.open_newwindow.restriction", 2)
driver = webdriver.Firefox(browser_profile=fp)
el problema es que esas preferencias preestablecidas para otros valores y son congelado al menos selenio 3.4.0. Cuando usa el perfil para configurarlos con el enlace Java, aparece un excepción y con el enlace de python, los nuevos valores se ignoran.
En Java hay una forma de establecer esas preferencias sin especificar un objeto de perfil al hablar con conductor de geckopero parece que aún no está implementado en el enlace de python:
FirefoxOptions options = new FirefoxOptions().setProfile(fp);
options.addPreference("browser.link.open_newwindow", 3);
options.addPreference("browser.link.open_newwindow.restriction", 2);
FirefoxDriver driver = new FirefoxDriver(options);
La tercera opción hizo para de trabajar para python en selenio 3.4.0.
Las dos primeras opciones también parecían para de trabajar en selenio 3.4.0. Dependen de enviar un evento de tecla CTRL a un elemento. A primera vista parece que es un problema de la tecla CTRL, pero está fallando debido a la nueva función multiproceso de Firefox. Puede ser que esta nueva arquitectura imponga nuevas formas de hacerlo, o tal vez sea un problema de implementación temporal. De todos modos podemos desactivarlo a través de:
fp = webdriver.FirefoxProfile()
fp.set_preference("browser.tabs.remote.autostart", False)
fp.set_preference("browser.tabs.remote.autostart.1", False)
fp.set_preference("browser.tabs.remote.autostart.2", False)
driver = webdriver.Firefox(browser_profile=fp)
… y luego puede usar con éxito la primera forma.
- Sistema operativo: ganar 10,
- Pitón 3.8.1
from selenium import webdriver
import time
driver = webdriver.Firefox(executable_path=r'TO\Your\Path\geckodriver.exe')
driver.get('https://www.google.com/')
# Open a new window
driver.execute_script("window.open('');")
# Switch to the new window
driver.switch_to.window(driver.window_handles[1])
driver.get("http://stackoverflow.com")
time.sleep(3)
# Open a new window
driver.execute_script("window.open('');")
# Switch to the new window
driver.switch_to.window(driver.window_handles[2])
driver.get("https://www.reddit.com/")
time.sleep(3)
# close the active tab
driver.close()
time.sleep(3)
# Switch back to the first tab
driver.switch_to.window(driver.window_handles[0])
driver.get("https://bing.com")
time.sleep(3)
# Close the only tab, will also close the browser.
driver.close()
Referencia: Necesito ayuda para abrir una nueva pestaña en Selenium

selenio no detectado
En una discusión, Simon mencionó claramente que:
Si bien el tipo de datos utilizado para almacenar la lista de identificadores puede ordenarse por inserción, el orden en el que la implementación de WebDriver itera sobre los identificadores de ventana para insertarlos no tiene ningún requisito para ser estable. El orden es arbitrario.
Utilizando Selenio v3.x abrir un sitio web en un Nueva pestaña a través de Pitón es mucho más fácil ahora. Tenemos que inducir un WebDriverWait por number_of_windows_to_be(2)
y luego recopilar los identificadores de ventana cada vez que abrimos una nueva pestaña/ventana y finalmente iterar a través de los identificadores de ventana y switchTo().window(newly_opened)
según sea necesario. Aquí hay una solución donde puede abrir http://www.google.co.in
en el PESTAÑA inicial y https://www.yahoo.com
en el TAB adyacente:
-
Bloque de código:
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
options = webdriver.ChromeOptions()
options.add_argument("start-maximized")
options.add_argument('disable-infobars')
driver = webdriver.Chrome(chrome_options=options, executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
driver.get("http://www.google.co.in")
print("Initial Page Title is : %s" %driver.title)
windows_before = driver.current_window_handle
print("First Window Handle is : %s" %windows_before)
driver.execute_script("window.open('https://www.yahoo.com')")
WebDriverWait(driver, 10).until(EC.number_of_windows_to_be(2))
windows_after = driver.window_handles
new_window = [x for x in windows_after if x != windows_before][0]
driver.switch_to.window(new_window)
print("Page Title after Tab Switching is : %s" %driver.title)
print("Second Window Handle is : %s" %new_window)
-
Salida de la consola:
Initial Page Title is : Google
First Window Handle is : CDwindow-B2B3DE3A222B3DA5237840FA574AF780
Page Title after Tab Switching is : Yahoo
Second Window Handle is : CDwindow-D7DA7666A0008ED91991C623105A2EC4
-
Instantánea del navegador:

final
Puede encontrar la discusión basada en Java en La mejor manera de realizar un seguimiento e iterar a través de pestañas y ventanas usando WindowHandles usando Selenium
Las otras soluciones no funcionan para controlador de cromo v83.
En cambio, funciona de la siguiente manera, supongamos que solo hay 1 pestaña de apertura:
driver.execute_script("window.open('');")
driver.switch_to.window(driver.window_handles[1])
driver.get("https://www.example.com")
Si ya hay más de 1 pestaña abierta, primero debe obtener el índice de la última pestaña recién creada y cambiar a la pestaña antes de llamar a la url (crédito a tylerl):
driver.execute_script("window.open('');")
driver.switch_to.window(len(driver.window_handles)-1)
driver.get("https://www.example.com")

Keiwan
Después de luchar durante tanto tiempo, el siguiente método funcionó para mí:
driver.find_element_by_tag_name('body').send_keys(Keys.CONTROL + 't')
driver.find_element_by_tag_name('body').send_keys(Keys.CONTROL + Keys.TAB)
windows = driver.window_handles
time.sleep(3)
driver.switch_to.window(windows[1])