【发布时间】:2019-12-13 06:40:42
【问题描述】:
我在 Eclipse 中,编写 Java GUI/脚本,运行无头 chromedriver,但在尝试加载 html2canvas.js 时遇到问题 [1][2] 库,然后在浏览器中调用我在该库上编写的函数;我收到此代码的未定义错误:
String ss1ScriptLoc = "C:\\Users\\me\\Desktop\\resources\\html2canvas.min.js";
String ss2ScriptLoc = "C:\\Users\\me\\Desktop\\resources\\takeScreenShot.js";
je.executeScript(
"var headID1 = document.getElementsByTagName('head')[0]; "
+ "var newScript1 = document.createElement('script'); "
+ "newScript1.type = 'text/javascript'; "
+ "newScript1.src = '" + ss1ScriptLoc + "'; "
+ "headID1.appendChild(newScript1); "
+ "var headID2 = document.getElementsByTagName('head')[0]; "
+ "var newScript2 = document.createElement('script'); "
+ "newScript2.type = 'text/javascript'; "
+ "newScript2.src = '" + ss2ScriptLoc + "'; "
+ "headID2.appendChild(newScript2); "
+ "$(document).ready( function () { takeScreenShot(); });"
);
这会导致未定义函数“takeScreenShot();”的错误我以为我已经在本地 .js 文件中定义了。
Starting ChromeDriver 75.0.3770.140 (-refs/branch-heads/3770@{#1155}) on port 48415
Only local connections are allowed.
Please protect ports used by ChromeDriver and related test frameworks to prevent access by malicious code.
Aug 05, 2019 9:36:53 AM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: W3C
java.util.concurrent.ExecutionException: org.openqa.selenium.JavascriptException: javascript error: takeScreenShot is not defined
(Session info: headless chrome=75.0.3770.142)
Caused by: org.openqa.selenium.JavascriptException: javascript error: takeScreenShot is not defined
(Session info: headless chrome=75.0.3770.142)
Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:25:48'
System info: host: '', ip: '', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '1.8.0_191'
Driver info: org.openqa.selenium.chrome.ChromeDriver
Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 75.0.3770.142, chrome: {chromedriverVersion: 75.0.3770.140 (2d9f97485c7b..., userDataDir: C:\Users\me\AppData\Lo...}, goog:chromeOptions: {debuggerAddress: localhost:55906}, javascriptEnabled: true, networkConnectionEnabled: false, pageLoadStrategy: normal, platform: XP, platformName: XP, proxy: Proxy(), setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 30000}, unhandledPromptBehavior: dismiss and notify}
Session ID:
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.openqa.selenium.remote.http.W3CHttpResponseCodec.createException(W3CHttpResponseCodec.java:187)
at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:122)
at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:49)
at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:158)
at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:83)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:552)
at org.openqa.selenium.remote.RemoteWebDriver.executeScript(RemoteWebDriver.java:489)
at App.getScreenShot(App.java:170)
at javax.swing.SwingWorker$1.call(SwingWorker.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at javax.swing.SwingWorker.run(SwingWorker.java:334)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
edit1:添加了这个 sn-p,经过测试,可以工作,但实际上并没有做任何事情。
je.executeScript("");
je.executeScript("document.body.onload = myCustomFunc();"
+ "function myCustomFunc() { console.log('hello world'); }"
);
我将这两个库 .js 文件读入 List,然后制作了一个大的 StringBuilder,将所有元素附加到 StringBuilder,然后添加了 takeScreenShot() 函数来代替 myCustomFunc()。不会抛出任何错误,但也不会生成下载的屏幕截图文件。
edit2:我的加载函数
private String fileToJSString(final String inScriptFile) {
Path p = Paths.get(inScriptFile);
if (!Files.exists(p)) {
System.err.println("fileToJSString : error, file does not exist");
return null;
}
List<String> lines = null;
try {
lines = Files.readAllLines(Paths.get(inScriptFile));
} catch (IOException e) {
e.printStackTrace();
}
if (lines == null) {
System.err.println("fileToJSString : error, no lines read from file");
return null;
}
StringBuilder sb = new StringBuilder();
for (String s : lines)
sb.append(s.trim() + " ");
return sb.toString();
}
edit3:根据@jay-mattinson 的建议,我尝试加载脚本,但是运行时字符串变量不适用于 html2canvas.js 库(特殊字符太多 - 请参阅前面的实际文件的链接/以上在这篇文章中)
String ss1ScriptLoc = "C:\\Users\\me\\Desktop\\resources\\html2canvas.min.js";
String ss2ScriptLoc = "C:\\Users\\me\\Desktop\\resources\\takeScreenShot.js";
String jsScript1 = fileToJSString(ss1ScriptLoc);
String jsScript2 = fileToJSString(ss2ScriptLoc);
JavascriptExecutor je = (JavascriptExecutor) this.driver;
je.executeScript(
"var headID = document.getElementsByTagName('head')[0]; "
+ "var newScript = document.createElement('script'); "
+ "newScript.type = 'text/javascript'; "
+ "var code = {" + jsScript1 + " " + jsScript2 + "};"
+ "newScript.appendChild(document.createTextNode(code));"
+ "headID.appendChild(newScript); "
+ "$(document).ready( function () { takeScreenShot(); });"
);
运行时抛出的特定错误;
Caused by: org.openqa.selenium.WebDriverException: unknown error: Runtime.evaluate threw exception: SyntaxError: Unexpected token !
edit4:这是我编写的基于 html2canvas 的函数,用于抓取网页上的表格图像;
function takeScreenShot() {
if (document.getElementsByClassName("abc-top") == null) {
console.log('not on the right web page with the right content. stopping script');
return;
}
var hiddenLinkObj = document.createElement('a');
hiddenLinkObj.setAttribute('href', '');
hiddenLinkObj.setAttribute('id', '');
document.body.insertBefore(hiddenLinkObj, document.body.childNodes[0]);
var s1 = window.location.href;
var idx = s1.lastIndexOf('/');
var res = s1.substring(idx + 1, s1.length);
hiddenLinkObj.setAttribute('download', 's' + res + '-s.png');
var partA = document.querySelector('[abc-show="showInfo"]');
var partB = partA.getElementsByClassName('row');
var partC = partB[3].childNodes[0];
partC.setAttribute('style', 'background-color:#fafafa');
var result = partC;
html2canvas(
result, {
onrendered: function(canvas) {
var myImage = canvas.toDataURL("image/png");
hiddenLinkObj.setAttribute('href', myImage.replace("image/png", "image/octet-stream"));
hiddenLinkObj.click();
}
}
);
}
所以我的问题/问题:为什么在 takeScreenShot.js 文件中定义和加载它时会出现未定义的函数错误? - 如何加载合适大小的 html2canvas JS 库和第二个/short 库包含我基于 html2canvas 库编写的单个 JS 函数并在 selenium 中执行我的函数? -
我猜这是因为我缺乏 JavaScript 知识,而且我错过了一个明显的错误。任何和所有帮助表示赞赏。
【问题讨论】:
-
您正在将本地路径传递到页面的脚本 SRC。此外,您不需要为脚本创建标记。 Selenium 将为您做到这一点。作为旁注,Selenium 可以为您截取屏幕截图: File full_scrn = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
标签: javascript java selenium selenium-webdriver