Откройте web в новой вкладке Selenium + Python
Итак, я пытаюсь открыть веб-сайты на новых вкладках внутри моего WebDriver. Я хочу сделать это, потому что открытие нового WebDriver для каждого веб-сайта занимает около 3,5 секунд с помощью PhantomJS, я хочу больше скорости...
Я использую многопроцессорный python script, и я хочу получить некоторые элементы с каждой страницы, поэтому рабочий процесс выглядит следующим образом:
Open Browser
Loop throught my array
For element in array -> Open website in new tab -> do my business -> close it
Но я не могу найти способ добиться этого.
Вот код, который я использую. Это происходит навсегда между веб-сайтами, мне нужно, чтобы это было быстро... Другие инструменты разрешены, но я не знаю слишком много инструментов для утилизации содержимого веб-сайта, загружаемого с помощью JavaScript (divs, создаваемые при возникновении какого-либо события при загрузке и т.д.). почему мне нужен Selenium... BeautifulSoup не может использоваться для некоторых моих страниц.
#!/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()
Ответы
Ответ 1
Вы можете добиться открытия/закрытия вкладки с помощью комбинации клавиш COMMAND + T или COMMAND + W (OSX). В других ОС вы можете использовать CONTROL + T/CONTROL + W.
В селене вы можете подражать такому поведению. Вам нужно будет создать один веб-драйвер и столько вкладок, сколько нужно тестов.
Вот это код.
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()
Ответ 2
Это общий код, адаптированный из других примеров:
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()
Возможные пути:
-
Отправка <CTRL> + <T>
в один элемент
#open tab
driver.find_element_by_tag_name('body').send_keys(Keys.CONTROL + 't')
-
Отправка <CTRL> + <T>
через цепочки действий
ActionChains(driver).key_down(Keys.CONTROL).send_keys('t').key_up(Keys.CONTROL).perform()
-
Выполнение фрагмента javascript
driver.execute_script('''window.open("http://bings.com","_blank");''')
Чтобы достичь этого, вам необходимо убедиться, что предпочтения browser.link.open_newwindow и browser.link.open_newwindow.restriction. Значения по умолчанию в последних версиях в порядке, иначе вам, возможно, понадобится:
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)
проблема в том, что эти предпочтения заданы другие значения и заморожены, по крайней мере, селен 3.4.0. Когда вы используете профиль, чтобы установить их с помощью привязки java, появляется исключение и с привязкой к python новые значения игнорируются.
В Java есть способ установить эти настройки без указания объекта профиля при разговоре с geckodriver, но он пока еще не реализован в привязке 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);
Третий вариант: перестать работать для python в selenium 3.4.0.
Первые две опции также казались прекратить работу в selenium 3.4.0. Они зависят от отправки ключевого события CTRL в элемент. На первый взгляд кажется, что это проблема ключа CTRL, но он терпит неудачу из-за новой функции многопроцессорности Firefox. Может быть, эта новая архитектура навязывает новые способы сделать это или, может быть, является временной проблемой реализации. В любом случае мы можем отключить его через:
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)
... и затем вы можете успешно использовать первый способ.
Ответ 3
browser.execute_script('''window.open("http://bings.com","_blank");''')
Где браузер - это webDriver
Ответ 4
В обсуждении Саймон четко упомянул, что:
Хотя тип данных, используемый для хранения списка дескрипторов, может быть упорядочен путем вставки, порядок, в котором реализация WebDriver выполняет итерации по дескрипторам окна для их вставки, не требует стабильности. Порядок произвольный.
Используя Selenium v3.x, открыть веб-сайт в новой вкладке через Python теперь намного проще. Нам нужно вызвать WebDriverWait для number_of_windows_to_be(2)
, а затем собирать дескрипторы окна каждый раз, когда мы открываем новую вкладку/окно, и, наконец, перебираем дескрипторы окна и switchTo().window(newly_opened)
по мере необходимости. Вот решение, в котором вы можете открыть http://www.google.co.in
в исходной вкладке и https://www.yahoo.com
в соседней вкладке:
Блок кода:
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)
Консольный вывод:
Initial Page Title is : Google
First Window Handle is : CDwindow-B2B3DE3A222B3DA5237840FA574AF780
Page Title after Tab Switching is : Yahoo
Second Window Handle is : CDwindow-D7DA7666A0008ED91991C623105A2EC4
Снимок браузера:
![multiple__tabs]()
Outro
Обсуждение на основе java можно найти в Лучшем способе отслеживать и перебирать вкладки и окна, используя WindowHandles, используя Selenium.
Ответ 5
После долгой работы метод ниже работал у меня:
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])
Ответ 6
Основание определения на сайте селена:
Прежде всего, для автоматизации веб-приложений в целях тестирования, но, конечно, не ограничивается только этим. Скучные задачи администрирования через Интернет могут (и должны!) Также быть автоматизированы.
вы видите, что главная цель селена предназначена для тестирования, а кроме того, вы можете автоматизировать задачи администрирования, не просматривая веб-сайты.
работа с такой штукой для ползания - это просто трата времени
Я думаю, вам следует сосредоточиться на сканировании, взгляните на http://scrapy.org
это наиболее распространенная структура в python для извлечения данных с веб-сайтов.
Ответ 7
Я очень долго пытался дублировать вкладки в Chrome, используя action_keys и send_keys на теле. Единственное, что сработало для меня, это ответ здесь. Это то, как моя дублированная вкладка определенно выглядела, вероятно, не самая лучшая, но она прекрасно работает для меня.
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)+"')")
Он в основном запускает Java изнутри Python, это невероятно полезно. Надеюсь, это кому-нибудь поможет.
Примечание: я использую Ubuntu, это не должно иметь никакого значения, но если это не работает для вас, это может быть причиной.
Ответ 8
Как ни странно, так много ответов, и все они используют суррогаты, такие как JS и сочетания клавиш, вместо того, чтобы просто использовать функцию селена:
def newTab(driver, url="about:blank"):
wnd = driver.execute(selenium.webdriver.common.action_chains.Command.NEW_WINDOW)
handle = wnd["value"]["handle"]
driver.switch_to.window(handle)
driver.get(url) # changes the handle
return driver.current_window_handle