Откройте 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

Обсуждение на основе можно найти в Лучшем способе отслеживать и перебирать вкладки и окна, используя 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