在新选项卡Selenium+中打开web;python

在新选项卡Selenium+中打开web;python,python,selenium,webdriver,phantomjs,java,Python,Selenium,Webdriver,Phantomjs,Java,因此,我尝试在我的WebDriver中的新选项卡上打开网站。我想这样做,因为使用PhantomJS为每个网站打开一个新的WebDriver大约需要3.5秒,我想要更快 我使用的是一个多进程python脚本,我想从每个页面获取一些元素,因此工作流如下所示: Open Browser Loop throught my array For element in array -> Open website in new tab -> do my business -> close i

因此,我尝试在我的WebDriver中的新选项卡上打开网站。我想这样做,因为使用PhantomJS为每个网站打开一个新的WebDriver大约需要3.5秒,我想要更快

我使用的是一个多进程python脚本,我想从每个页面获取一些元素,因此工作流如下所示:

Open Browser

Loop throught my array
For element in array -> Open website in new tab -> do my business -> close it
但我找不到任何方法来实现这一点

这是我正在使用的代码。它需要永远之间的网站,我需要它是快速的。。。其他工具是允许的,但我不知道有太多的工具,用于废弃使用JavaScript加载的网站内容(加载时触发某些事件时创建的div等),这就是为什么我需要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()

您可以通过组合键COMMAND+T或COMMAND+W(OSX)来实现选项卡的打开/关闭。在其他OSs上,您可以使用CONTROL+T/CONTROL+W

在selenium中,您可以模拟这种行为。 您需要创建一个webdriver和所需测试的尽可能多的选项卡

这是代码

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()

其中浏览器网络驱动程序

经过这么长时间的努力,下面的方法对我很有效:

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])

这是根据其他示例改编的通用代码:

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()
可能的方法是:

  • +
    发送到一个元素

    #open tab
    driver.find_element_by_tag_name('body').send_keys(Keys.CONTROL + '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");''')
    
    为了实现这一点,您需要确保正确设置了首选项和。最后版本中的默认值正常,否则您可能需要:

    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)
    
    问题是,这些首选项预设为且已冻结,至少为selenium 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);
    
  • 第三个选项在selenium 3.4.0中对python做了修改

    在selenium 3.4.0中,前两个选项似乎也适用。它们确实依赖于向元素发送CTRL键事件。乍一看,这似乎是CTRL键的问题,但由于新的错误,它失败了。这可能是因为这种新的体系结构采用了新的实现方法,也可能是一个暂时的实现问题。无论如何,我们可以通过以下方式禁用它:

    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)
    

    。。。然后你可以成功地使用第一种方法。

    在一次讨论中,Simon明确提到:

    虽然用于存储句柄列表的数据类型可以按插入顺序排列,但WebDriver实现在窗口句柄上迭代以插入句柄的顺序不需要稳定。排序是任意的


    现在,使用SeleniumV3.x通过Python在新选项卡中打开网站要容易得多。我们必须将
    number\u of \u windows\u的WebDriverWait设置为\u be(2)
    ,然后在每次打开新选项卡/窗口时收集窗口句柄,最后根据需要迭代窗口句柄和
    switch to()。窗口(新打开的)
    。这里有一个解决方案,您可以在其中打开
    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
      
    • 浏览器快照:


    奥特罗
    您可以在

    中找到基于的讨论。我花了很长时间在Chrome中使用操作键和发送键复制选项卡。唯一对我有用的是答案。这就是我的复制标签def最终的样子,可能不是最好的,但对我来说效果很好

    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)+"')")
    
    它基本上是从python内部运行一些java,非常有用。希望这对别人有帮助


    注意:我使用的是Ubuntu,它应该不会有什么不同,但如果它对你不起作用,这可能就是原因。

    奇怪的是,这么多答案,所有答案都使用了JS和键盘快捷键等替代项,而不仅仅是使用selenium功能:

    def newTab(驱动程序,url=“about:blank”): wnd=driver.execute(selenium.webdriver.common.action\u chains.Command.NEW\u窗口) handle=wnd[“值”][“句柄”] 驾驶员。切换到。车窗(把手) driver.get(url)#更改句柄 返回driver.current\u window\u句柄
    • OS:Win10
    • Python 3.8.1
      • 硒==3.141.0

    参考资料:

    其他解决方案不适用于chrome驱动程序v83

    相反,它的工作原理如下,假设只有一个打开选项卡:

    driver.execute_script("window.open('');")
    driver.switch_to.window(driver.window_handles[1])
    driver.get("https://www.example.com")
    
    如果已存在多个打开的选项卡,则应首先获取上次新建选项卡的索引,并在调用url之前切换到该选项卡(请参见):


    据我所知,在chrome浏览器的同一窗口中打开新的空选项卡是不可能的,但您可以使用web链接打开新选项卡

    到目前为止,我在网上冲浪,在这个问题上我得到了很好的工作内容。 请尽量按照步骤进行操作,不要遗漏

    import selenium.webdriver as webdriver
    from selenium.webdriver.common.keys import Keys
    
    driver = webdriver.Chrome()
    driver.get('https://www.google.com?q=python#q=python')
    first_link = driver.find_element_by_class_name('l')
    
    # Use: Keys.CONTROL + Keys.SHIFT + Keys.RETURN to open tab on top of the stack 
    first_link.send_keys(Keys.CONTROL + Keys.RETURN)
    
    # Switch tab to the new tab, which we will assume is the next one on the right
    driver.find_element_by_tag_name('body').send_keys(Keys.CONTROL + Keys.TAB)
    
    driver.quit()
    
    我认为这是目前为止更好的解决方案

    信用证:

    我会坚持这一点

    这是一个打开新选项卡并切换到该选项卡的函数:

    导入时间
    从selenium.webdriver.common.action\u链导入ActionChains
    def在新选项卡中打开(驱动程序、元素、切换到新选项卡=真):
    基本\u句柄=驱动程序。当前\u窗口\u句柄
    #做一些动作
    行动链(驱动程序)\
    .将_移动到_元素(元素)\
    .key_向下(Keys.COMMAND)\
    。单击()\
    .key\u up(key.COMMAND)\
    .perform()
    #你应该切换到新标签吗?
    如果切换到新选项卡:
    新的\u句柄=[x代表驱动程序中的x。如果x!=基本\u句柄,则窗口\u句柄]
    断言len new_handle==1#假设yo
    
    driver.execute_script("window.open('');")
    driver.switch_to.window(driver.window_handles[1])
    driver.get("https://www.example.com")
    
    driver.execute_script("window.open('');")
    driver.switch_to.window(len(driver.window_handles)-1)
    driver.get("https://www.example.com")
    
    import selenium.webdriver as webdriver
    from selenium.webdriver.common.keys import Keys
    
    driver = webdriver.Chrome()
    driver.get('https://www.google.com?q=python#q=python')
    first_link = driver.find_element_by_class_name('l')
    
    # Use: Keys.CONTROL + Keys.SHIFT + Keys.RETURN to open tab on top of the stack 
    first_link.send_keys(Keys.CONTROL + Keys.RETURN)
    
    # Switch tab to the new tab, which we will assume is the next one on the right
    driver.find_element_by_tag_name('body').send_keys(Keys.CONTROL + Keys.TAB)
    
    driver.quit()
    
    tabs = {}
    
    def new_tab():
        global browser
        hpos = browser.window_handles.index(browser.current_window_handle)
        browser.execute_script("window.open('');")
        browser.switch_to.window(browser.window_handles[hpos + 1])
        return(browser.current_window_handle)
        
    def switch_tab(name):
        global tabs
        global browser
        if not name in tabs.keys():
            tabs[name] = {'window_handle': new_tab(), 'url': url+name}
            browser.get(tabs[name]['url'])
        else:
            browser.switch_to.window(tabs[name]['window_handle'])
    
    driver.find_element_by_tag_name('body').send_keys(Keys.CONTROL + 't')
    ActionChains(driver).key_down(Keys.CONTROL).send_keys('t').key_up(Keys.CONTROL).perform()
    
    <!DOCTYPE html>
    <html><body>
    <a id="open_new_window" href="about:blank" target="_blank">open a new window</a>
    </body></html>
    
    # master
    master_handle = driver.current_window_handle
    helper = os.path.join(os.path.dirname(os.path.abspath(__file__)), "helper.html")
    driver.get(helper)
    
    # open new tabs
    for _ in range(100):
        window_handle = driver.window_handles          # current state
        driver.switch_to_window(master_handle)
        driver.find_element_by_id("open_new_window").click()
        window_handle = set(driver.window_handles).difference(window_handle).pop()
        print("new window handle:", window_handle)
    
    #Change the method of finding the element if needed
    self.find_element_by_xpath(element).send_keys(Keys.CONTROL + Keys.ENTER)
    
    # Open a new Tab
    driver.execute_script("window.open('');")
    
    # Switch to the new window and open URL B
    driver.switch_to.window(driver.window_handles[1])
    driver.get(tab_url)
    
    from selenium import webdriver
    import time
    
    driver = webdriver.Firefox()
    driver.get('https://www.google.com')
    
    driver.execute_script("window.open('');")
    time.sleep(5)
    
    driver.switch_to.window(driver.window_handles[1])
    driver.get("https://facebook.com")
    time.sleep(5)
    
    driver.close()
    time.sleep(5)
    
    driver.switch_to.window(driver.window_handles[0])
    driver.get("https://www.yahoo.com")
    time.sleep(5)
    
    #driver.close()