在新选项卡中打开网页 Selenium + Python

2024-11-27 10:43:00
admin
原创
14
摘要:问题描述:因此,我尝试在 WebDriver 中的新选项卡上打开网站。我想这样做,因为使用 PhantomJS 为每个网站打开一个新的 WebDriver 大约需要 3.5 秒,我希望速度更快...我正在使用多进程 python 脚本,并且想要从每个页面获取一些元素,因此工作流程如下:Open Browser...

问题描述:

因此,我尝试在 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()

解决方案 1:

编者注:此答案不再适用于新版本的 Selenium。请参阅此评论。


您可以通过组合键COMMAND+TCOMMAND+ W(OSX) 来打开/关闭标签页。在其他操作系统上,您可以使用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()

解决方案 2:

browser.execute_script('''window.open("http://bings.com","_blank");''')

浏览器是webDriver

解决方案 3:

这是根据另一个示例改编的常用代码:

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

可能的方式有:

  1. 发送<CTRL> + <T>到一个元素

#open tab
driver.find_element_by_tag_name('body').send_keys(Keys.CONTROL + 't')
  1. <CTRL> + <T>通过动作链发送

ActionChains(driver).key_down(Keys.CONTROL).send_keys('t').key_up(Keys.CONTROL).perform()
  1. 执行 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)

问题是这些首选项预设为其他值,并且 至少在 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 键的问题,但由于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)

...然后您就可以成功使用第一种方法了。

解决方案 4:

  • 操作系统:Win 10,

  • Python 3.8.1

+ 硒==3.141.0
from selenium import webdriver
import time

driver = webdriver.Firefox(executable_path=r'TOYourPathgeckodriver.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()

参考:需要帮助在 Selenium 中打开新标签

解决方案 5:

其他解决方案不适用于 chrome driver v83。

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

driver.execute_script("window.open('');")
driver.switch_to.window(driver.window_handles[1])
driver.get("https://www.example.com")

如果已打开多个标签页,则应首先获取最后一个新创建的标签页的索引,然后切换到该标签页,然后再调用 URL:

driver.execute_script("window.open('');")
driver.switch_to.window(len(driver.window_handles)-1)
driver.get("https://www.example.com")

解决方案 6:

Selenium 4.0.0版本支持以下操作:

  • 打开新标签页尝试:

driver.switch_to.new_window()

  • 切换到特定选项卡(请注意tabID从 0 开始):

driver.switch_to.window(driver.window_handles[tabID])

解决方案 7:

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

虽然用于存储句柄列表的数据类型可以按插入顺序排列,但 WebDriver 实现遍历窗口句柄以插入它们的顺序并不要求稳定。顺序是任意的。


现在,使用Selenium v​​3.x通过Python在新选项卡中打开网站变得容易得多。每次打开新选项卡/窗口时,我们都必须引发WebDriverWait,然后收集窗口句柄,最后根据需要遍历窗口句柄。这是一个解决方案,您可以在初始选项卡相邻选项卡中打开:number_of_windows_to_be(2)`switchTo().window(newly_opened)http://www.google.co.inhttps://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:UtilityBrowserDriverschromedriver.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
  • 浏览器快照:

多个标签


结尾

您可以找到Java 语言基于讨论使用 Selenium 使用 WindowHandles 跟踪和遍历选项卡和窗口的最佳方法

解决方案 8:

尝试一下它会起作用:

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

解决方案 9:

经过长时间的努力,下面的方法对我有用:

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

解决方案 10:

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

https://www.edureka.co/community/52772/close-active-current-without-looking-browser-selenium-python

解决方案 11:

仅供将来参考,简单的方法可以如下:

driver.switch_to.new_window()
t=driver.window_handles[-1]# Get the handle of new tab
driver.switch_to.window(t)
driver.get(target_url) # Now the target url is opened in new tab

解决方案 12:

奇怪的是,有这么多的答案,他们全都使用 JS 和键盘快捷键之类的代理,而不仅仅是使用 selenium 功能:

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

解决方案 13:

为此我会坚持使用ActionChains 。

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

import time
from selenium.webdriver.common.action_chains import ActionChains

def open_in_new_tab(driver, element, switch_to_new_tab=True):
    base_handle = driver.current_window_handle
    # Do some actions
    ActionChains(driver) \n        .move_to_element(element) \n        .key_down(Keys.COMMAND) \n        .click() \n        .key_up(Keys.COMMAND) \n        .perform()
    
    # Should you switch to the new tab?
    if switch_to_new_tab:
        new_handle = [x for x in driver.window_handles if x!=base_handle]
        assert len new_handle == 1 # assume you are only opening one tab at a time
        
        # Switch to the new window
        driver.switch_to.window(new_handle[0])

        # I like to wait after switching to a new tab for the content to load
        # Do that either with time.sleep() or with WebDriverWait until a basic
        # element of the page appears (such as "body") -- reference for this is 
        # provided below
        time.sleep(0.5)        

        # NOTE: if you choose to switch to the window/tab, be sure to close
        # the newly opened window/tab after using it and that you switch back
        # to the original "base_handle" --> otherwise, you'll experience many
        # errors and a painful debugging experience...

应用该函数的方法如下:

# Remember your starting handle
base_handle = driver.current_window_handle

# Say we have a list of elements and each is a link:
links = driver.find_elements_by_css_selector('a[href]')

# Loop through the links and open each one in a new tab
for link in links:
    open_in_new_tab(driver, link, True)
    
    # Do something on this new page
    print(driver.current_url)
    
    # Once you're finished, close this tab and switch back to the original one
    driver.close()
    driver.switch_to.window(base_handle)
    
    # You're ready to continue to the next item in your loop

您可以按照以下方法等待页面加载完成。

解决方案 14:

你可以使用它来打开新标签

driver.execute_script("window.open('http://google.com', 'new_window')")

解决方案 15:

这对我有用:-

link = "https://www.google.com/"
driver.execute_script('''window.open("about:blank");''')  # Opening a blank new tab
driver.switch_to.window(driver.window_handles[1])  # Switching to newly opend tab
driver.get(link)

解决方案 16:

只需使用它来打开新窗口即​​可(例如):

driver.find_element_by_link_text("Images").send_keys(Keys.CONTROL + Keys.RETURN)

解决方案 17:

我尝试了很长时间,在 Chrome 中使用 body 上的 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)+"')")

它基本上在 Python 内部运行一些 Java,非常有用。希望这对某些人有帮助。

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

解决方案 18:

据我所知,无法在 Chrome 浏览器的同一窗口内打开新的空白标签页,但您可以使用网络链接打开新标签页。

到目前为止,我在网上搜索了有关这个问题的很好的内容。请尝试按照步骤操作,不要遗漏。

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

我认为这是迄今为止更好的解决方案。

来源:https://gist.github.com/lrhache/7686903

解决方案 19:

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

解决方案 20:

正如已经多次提到的,以下方法不再有效:

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

此外,driver.execute_script("window.open('');")它正在运行,但受到弹出窗口拦截器的限制。我同时处理数百个选项卡(使用scrapy进行网页抓取)。然而,在使用 JavaScript 打开 20 个新选项卡后,弹出窗口拦截器开始起作用window.open(''),从而破坏了我的爬虫程序。

为了解决问题,我将一个选项卡声明为“主”,该选项卡打开了以下内容helper.html

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

通过 JavaScript 关闭这些窗口window.close()没有问题。

解决方案 21:

#Change the method of finding the element if needed
self.find_element_by_xpath(element).send_keys(Keys.CONTROL + Keys.ENTER)

这将找到该元素并在新选项卡中打开它。self 只是用于 webdriver 对象的名称。

解决方案 22:

现在由 selenium 原生支持

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# Store the ID of the original window
original_window = driver.current_window_handle    

# Opens a new window and switches to new window
driver.switch_to.new_window('window')

# Check we don't have other windows open already
assert len(driver.window_handles) == 1

# Click the link which opens in a new window
driver.find_element(By.LINK_TEXT, "new window").click()

# Wait for the new window or tab
wait.until(EC.number_of_windows_to_be(2))

#Close the tab or window
driver.close()
#Switch back to the old tab or window
driver.switch_to.window(original_window)

参考:https://www.selenium.dev/documentation/webdriver/interactions/windows/

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   657  
  如何借鉴华为IPD体系优化企业研发?在当今竞争激烈的市场环境中,企业要想保持技术领先和产品竞争力,必须拥有一套高效且严谨的研发管理体系。华为作为全球领先的ICT解决方案提供商,其集成产品开发(IPD, Integrated Product Development)体系与质量管理体系(如ISO 9000系列)的融合实践,...
IPD项目管理   15  
  IPD流程图的7种经典绘制方法详解在产品开发领域,集成产品开发(Integrated Product Development,简称IPD)流程被广泛应用,以提高产品开发的效率和质量。IPD流程图作为这一流程的可视化工具,其绘制方法至关重要。本文将详细介绍七种经典的IPD流程图绘制方法,帮助项目管理人员和团队更好地理解和...
IPD研发管理体系   18  
  IPD流程:企业创新管理的核心引擎在当今快速变化的市场环境中,企业要想持续保持竞争力,就必须不断进行创新。而IPD(Integrated Product Development,集成产品开发)流程作为一种先进的产品开发管理模式,正逐渐成为众多企业提升创新能力、加速产品上市速度、降低开发成本的重要选择。本文将深入探讨IP...
IPD管理   18  
  IPD流程与传统产品开发流程的概述在产品开发领域,企业不断寻求高效、系统的管理方法以确保产品能够顺利从概念转化为市场成功的产品。集成产品开发(Integrated Product Development,简称IPD)流程与传统产品开发流程是两种截然不同的管理理念和方法。传统产品开发流程往往以职能部门为核心,各部门按顺序...
IPD流程中PDCP是什么意思   16  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用