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

2024-11-27 10:43:00
admin
原创
164
摘要:问题描述:因此,我尝试在 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/

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1247  
  IPD(Integrated Product Development)研发管理体系作为一种先进的产品开发管理模式,在众多企业中得到了广泛应用,助力企业提升产品开发效率、降低成本、增强市场竞争力。深入理解其核心要素,对于企业成功实施 IPD 研发管理体系至关重要。以下将对 IPD 研发管理体系的四大核心要素进行详细解析。...
IPD流程中的charter   19  
  IPD(Integrated Product Development)研发管理体系强调将产品开发视为一个完整的流程,从市场需求出发,整合企业的各种资源,实现产品的快速、高质量交付。在这个过程中,成本控制是至关重要的一环,它直接关系到产品的竞争力和企业的盈利能力。有效的成本控制能够确保在不牺牲产品质量和性能的前提下,降低...
IPD开发流程管理   22  
  IPD(Integrated Product Development)项目管理作为一种先进的产品开发管理模式,在众多企业中得到了广泛应用。它通过整合跨部门团队,实现从概念到产品上市的全流程高效管理,提升产品竞争力。深入探讨IPD项目管理的六个关键阶段,对于企业理解和运用这一模式,优化产品开发流程具有重要意义。概念阶段概...
IPD概念阶段   29  
  IPD(Integrated Product Development)流程管理作为一种先进的产品开发管理模式,旨在通过整合各种资源,实现产品开发的高效、协同与创新。在这一流程管理体系下,产品质量保障成为企业关注的核心要点之一。有效的产品质量保障策略不仅能够提升产品的市场竞争力,还能为企业赢得良好的声誉和客户忠诚度。接下...
华为IPD   24  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用