如何在加载/执行页面的任何其他脚本之前将Javascript注入/执行到页面中
Selenium: How to Inject/execute a Javascript in to a Page before loading/executing any other scripts of the page?
我使用selenium python webdriver来浏览一些页面。我想在加载和执行任何其他javascript代码之前将javascript代码注入到页面中。另一方面,我需要我的JS代码被执行作为该页面的第一个JS代码。硒有办法做到这一点吗?
我在谷歌上搜索了几个小时,但我找不到任何合适的答案!
Selenium现在支持Chrome Devtools Protocol (CDP) API,因此,在每个页面加载上执行脚本非常容易。下面是一个示例代码:
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {'source': 'alert("Hooray! I did it!")'})
并且它将为每个页面加载执行该脚本。更多相关信息请访问:
- Selenium文档:https://www.selenium.dev/documentation/en/support_packages/chrome_devtools/
- Chrome Devtools协议文档:https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-addScriptToEvaluateOnNewDocument
从1.0.9版本开始,selenium-wire已经获得了修改请求响应的功能。下面是这个功能的一个例子,它在页面到达浏览器之前将脚本注入到页面中。
import os
from seleniumwire import webdriver
from gzip import compress, decompress
from urllib.parse import urlparse
from lxml import html
from lxml.etree import ParserError
from lxml.html import builder
script_elem_to_inject = builder.SCRIPT('alert("injected")')
def inject(req, req_body, res, res_body):
# various checks to make sure we're only injecting the script on appropriate responses
# we check that the content type is HTML, that the status code is 200, and that the encoding is gzip
if res.headers.get_content_subtype() != 'html' or res.status != 200 or res.getheader('Content-Encoding') != 'gzip':
return None
try:
parsed_html = html.fromstring(decompress(res_body))
except ParserError:
return None
try:
parsed_html.head.insert(0, script_elem_to_inject)
except IndexError: # no head element
return None
return compress(html.tostring(parsed_html))
drv = webdriver.Firefox(seleniumwire_options={'custom_response_handler': inject})
drv.header_overrides = {'Accept-Encoding': 'gzip'} # ensure we only get gzip encoded responses
另一种远程控制浏览器并能够在页面内容加载之前注入脚本的方法是使用完全基于单独协议的库,例如:Chrome DevTools协议。我所知道的最有特色的是剧作家
如果您想在浏览器解析和执行页面的html之前注入一些内容,我建议您使用代理,例如Mitmproxy。
如果您无法修改页面内容,您可以使用代理,或者在浏览器中安装的扩展中使用内容脚本。在selenium中,您将编写一些代码,将脚本作为现有元素的一个子元素注入,但是您将无法在页面加载之前(当驱动程序的get()
调用返回时)运行它。
String name = (String) ((JavascriptExecutor) driver).executeScript(
"(function () { ... })();" ...
文档没有指定代码开始执行的时刻。您可能希望它在DOM开始加载之前完成,这样保证可能只适用于代理或扩展内容脚本路由。
如果您可以使用最小的工具来检测您的页面,您可能会检测到一个特殊的url查询参数的存在并加载额外的内容,但您需要使用内联脚本来完成。伪代码:
<html>
<head>
<script type="text/javascript">
(function () {
if (location && location.href && location.href.indexOf("SELENIUM_TEST") >= 0) {
var injectScript = document.createElement("script");
injectScript.setAttribute("type", "text/javascript");
//another option is to perform a synchronous XHR and inject via innerText.
injectScript.setAttribute("src", URL_OF_EXTRA_SCRIPT);
document.documentElement.appendChild(injectScript);
//optional. cleaner to remove. it has already been loaded at this point.
document.documentElement.removeChild(injectScript);
}
})();
</script>
...
所以我知道它已经有几年了,但我已经找到了一种方法来做到这一点,而不修改网页的内容,而不使用代理!我使用nodejs版本,但大概API是一致的其他语言以及。您需要做的是:
const {Builder, By, Key, until, Capabilities} = require('selenium-webdriver');
const capabilities = new Capabilities();
capabilities.setPageLoadStrategy('eager'); // Options are 'eager', 'none', 'normal'
let driver = await new Builder().forBrowser('firefox').setFirefoxOptions(capabilities).build();
await driver.get('http://example.com');
driver.executeScript('`
console.log('hello'
'`)
这个"急切"选项对我很有用。您可能需要使用"none"选项。文档:https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/capabilities_exports_PageLoadStrategy.html
编辑:请注意,'eager'选项尚未在Chrome中实现…
- 无法在通过jQuery的ajax加载的页面中执行javascript
- 在Safari执行javascript之前对其进行修改
- 如何在执行此特定onclick事件时执行JavaScript函数
- 如何在从浏览缓存加载页面时执行javascript
- 使用Rhino和ASE执行Javascript的区别
- 如何在加载完整页面后严格执行javascript代码
- 在动态加载的对话框中执行Javascript
- 在Sinatra中执行Javascript
- 通过AJAX加载页面并执行javascript和CSS
- 适用于多种浏览器的Selenium-需要能够执行javascript的webDriver
- 如何在seleniumwebdriver中执行javascript提示并等待接受输入
- 在window.open()生成的窗口中执行JavaScript
- AJAX成功回调-执行javascript时出现问题
- 通过指令在控制器中执行javascript函数
- 从React Native Android原生地执行JavaScript代码
- iframe未执行Javascript方法(PHP)
- 执行JavaScript代码,使用selenium webdriver或WatiN从控制台获取日志
- 通过web驱动程序异步执行Javascript
- 如何在长时间执行JavaScript期间显示微调器
- 点击困难时执行javascript函数