J'essaie donc d'ouvrir des sites Web sur de nouveaux onglets dans mon WebDriver. Je veux le faire, car l'ouverture d'un nouveau WebDriver pour chaque site Web prend environ 3,5 secondes à l'aide de PhantomJS, je veux plus de vitesse ...
J'utilise un multiprocessus python, et je veux obtenir des éléments de chaque page, donc le flux de travail est comme ceci:
Open Browser
Loop throught my array
For element in array -> Open website in new tab -> do my business -> close it
Mais je ne trouve aucun moyen d'y parvenir.
Voici le code que j'utilise. Cela prend une éternité entre les sites Web, j'en ai besoin pour être rapide ... D'autres outils sont autorisés, mais je ne connais pas trop d'outils pour supprimer le contenu du site Web qui se charge avec JavaScript (divs créées lorsqu'un événement est déclenché au chargement, etc.) pourquoi j'ai besoin de sélénium ... BeautifulSoup ne peut pas être utilisé pour certaines de mes pages.
#!/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,'/',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()
Vous pouvez réaliser l'ouverture/fermeture d'un onglet par la combinaison de touches COMMAND + T ou COMMAND + W (OSX). Sur d'autres OS, vous pouvez utiliser CONTROL + T / CONTROL + W.
Dans Selenium, vous pouvez émuler un tel comportement. Vous devrez créer un pilote Web et autant d'onglets que les tests dont vous avez besoin.
Ici, c'est le code.
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()
Il s'agit d'un code commun adapté d'autres exemples:
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()
les moyens possibles étaient:
Envoi <CTRL> + <T>
à un élément
#open tab
driver.find_element_by_tag_name('body').send_keys(Keys.CONTROL + 't')
Envoi <CTRL> + <T>
via des chaînes d'action
ActionChains(driver).key_down(Keys.CONTROL).send_keys('t').key_up(Keys.CONTROL).perform()
Exécutez un extrait javascript
driver.execute_script('''window.open("http://bings.com","_blank");''')
Pour ce faire, vous devez vous assurer que les préférences browser.link.open_newwindow et browser.link.open_newwindow.restriction sont correctement définies. Les valeurs par défaut dans les dernières versions sont correctes, sinon vous avez supposément besoin de:
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)
le problème est que ces préférences sont prédéfinies à autres valeurs et sont figées au moins Selenium 3.4.0. Lorsque vous utilisez le profil pour les définir avec la liaison Java, il y a une exception et avec la liaison python), les nouvelles valeurs sont ignoré.
Dans Java il y a un moyen de définir ces préférences sans spécifier d'objet de profil lors de la conversation avec geckodriver , mais il semble pas encore implémenté dans la liaison 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 troisième option a arrêter de fonctionner pour python dans Selenium 3.4.0.
Les deux premières options semblaient également cesser de fonctionner dans Selenium 3.4.0. Ils dépendent de l'envoi d'un événement de touche CTRL à un élément. À première vue, il semble que ce soit un problème de la clé CTRL, mais il échoue à cause de la nouvelle fonctionnalité multiprocessus de Firefox . Il se peut que cette nouvelle architecture impose de nouvelles façons de le faire, ou est peut-être un problème de mise en œuvre temporaire. Quoi qu'il en soit, nous pouvons le désactiver via:
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)
... et ensuite vous pouvez utiliser avec succès la première façon.
browser.execute_script('''window.open("http://bings.com","_blank");''')
Où navigateur est le webDriver
Au cours d'une discussion, Simon a clairement mentionné que:
Bien que le type de données utilisé pour stocker la liste des descripteurs puisse être ordonné par insertion, l'ordre dans lequel l'implémentation WebDriver parcourt les descripteurs de fenêtre pour les insérer n'a pas besoin d'être stable. La commande est arbitraire.
Utilisation de Selenium v3.x ouverture d'un site Web dans un nouvel onglet à Python est beaucoup plus facile maintenant. Nous devons induire un WebDriverWait pour number_of_windows_to_be(2)
puis collecter les poignées de fenêtre chaque fois que nous ouvrons un nouvel onglet/fenêtre et enfin itérons à travers les poignées de fenêtre et switchTo().window(newly_opened)
comme requis. Voici une solution où vous pouvez ouvrir http://www.google.co.in
dans le TAB initial et https://www.yahoo.com
dans le TAB adjacent :
Bloc de code:
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)
Sortie console:
Initial Page Title is : Google
First Window Handle is : CDwindow-B2B3DE3A222B3DA5237840FA574AF780
Page Title after Tab Switching is : Yahoo
Second Window Handle is : CDwindow-D7DA7666A0008ED91991C623105A2EC4
Instantané du navigateur:
Vous pouvez trouver la discussion basée sur Java dans Meilleur moyen de suivre et d'itérer à travers les onglets et les fenêtres en utilisant WindowHandles en utilisant Selenium
Après avoir lutté pendant si longtemps, la méthode ci-dessous a fonctionné pour moi:
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])
J'ai essayé pendant très longtemps de dupliquer des onglets dans Chrome fonctionnant en utilisant action_keys et send_keys sur le corps. La seule chose qui a fonctionné pour moi était une réponse ici . Ceci est à quoi ressemblaient mes onglets en double, probablement pas le meilleur, mais cela fonctionne bien pour moi.
def duplicate_tabs(number, chromewebdriver):
#Once on the page we want to open a bunch of tabs
url = chromewebdriver.current_url
for i in range(number):
print('opened tab: '+str(i))
chromewebdriver.execute_script("window.open('"+url+"', 'new_window"+str(i)+"')")
Il exécute essentiellement quelques Java de l'intérieur de python, c'est incroyablement utile. J'espère que cela aide quelqu'un.
Remarque: j'utilise Ubuntu, cela ne devrait pas faire de différence, mais si cela ne fonctionne pas pour vous, cela pourrait être la raison.