在新选项卡中打开网页 Selenium + Python
- 2024-11-27 10:43:00
- admin 原创
- 14
问题描述:
因此,我尝试在 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
+T
或COMMAND
+ 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()
可能的方式有:
发送
<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)
问题是这些首选项预设为其他值,并且 至少在 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 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: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/
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 项目管理必备:盘点2024年13款好用的项目管理软件