【问题标题】:How to overcome an HTMLUnit ScriptException?如何克服 HTMLUnit ScriptException?
【发布时间】:2013-12-17 09:29:51
【问题描述】:

我遇到了一行代码的问题,它可能会触发一些 js 函数并导致异常,我该如何解决这个问题?

box.setText(link.toString());
client.waitForBackgroundJavaScriptStartingBefore(10000);
box.dblClick(); //this line cause the exception

Exception in thread "main" ======= EXCEPTION START ========
EcmaError: lineNumber=[0] column=[0] lineSource=[function () {] name=[ReferenceError] sourceName=[onclick event for HtmlDivision[<div class="_119 stat_elem focus_target mtm mbl _5bsm _6dh _51z6" id="u_0_k" data-location="maincolumn" onclick="Bootloader.loadComponents(&quot;ComposerXControllerBootload&quot;, emptyFunction);">] in https://www.facebook.com/?_fb_noscript=1] message=[ReferenceError: "Bootloader" is not defined.]
com.gargoylesoftware.htmlunit.ScriptException: ReferenceError: "Bootloader" is not defined.
    at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine$HtmlUnitContextAction.run(JavaScriptEngine.java:684)
    at net.sourceforge.htmlunit.corejs.javascript.Context.call(Context.java:602)
    at net.sourceforge.htmlunit.corejs.javascript.ContextFactory.call(ContextFactory.java:507)
    at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine.callFunction(JavaScriptEngine.java:616)
    at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine.callFunction(JavaScriptEngine.java:591)
    at com.gargoylesoftware.htmlunit.html.HtmlPage.executeJavaScriptFunctionIfPossible(HtmlPage.java:985)
    at com.gargoylesoftware.htmlunit.javascript.host.EventListenersContainer.executeEventHandler(EventListenersContainer.java:210)
    at com.gargoylesoftware.htmlunit.javascript.host.EventListenersContainer.executeBubblingListeners(EventListenersContainer.java:230)
    at com.gargoylesoftware.htmlunit.javascript.host.Node.fireEvent(Node.java:804)
    at com.gargoylesoftware.htmlunit.javascript.host.Node.fireEvent(Node.java:738)
    at com.gargoylesoftware.htmlunit.html.HtmlElement$1.run(HtmlElement.java:869)
    at net.sourceforge.htmlunit.corejs.javascript.Context.call(Context.java:602)
    at net.sourceforge.htmlunit.corejs.javascript.ContextFactory.call(ContextFactory.java:507)
    at com.gargoylesoftware.htmlunit.html.HtmlElement.fireEvent(HtmlElement.java:874)
    at com.gargoylesoftware.htmlunit.html.HtmlElement.doClickFireClickEvent(HtmlElement.java:1311)
    at com.gargoylesoftware.htmlunit.html.HtmlElement.click(HtmlElement.java:1253)
    at com.gargoylesoftware.htmlunit.html.HtmlElement.click(HtmlElement.java:1205)
    at com.gargoylesoftware.htmlunit.html.HtmlElement.dblClick(HtmlElement.java:1351)
    at com.gargoylesoftware.htmlunit.html.HtmlElement.dblClick(HtmlElement.java:1326)
    at prototype.Profile.postLinkOnWall(Profile.java:225)
    at html.Log.findNext(Log.java:150)
    at prototype.Prtp.main(Prtp.java:49)
Caused by: net.sourceforge.htmlunit.corejs.javascript.EcmaError: ReferenceError: "Bootloader" is not defined.
    at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.constructError(ScriptRuntime.java:3603)
    at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.constructError(ScriptRuntime.java:3587)
    at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.notFoundError(ScriptRuntime.java:3657)
    at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.nameOrFunction(ScriptRuntime.java:1749)
    at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.name(ScriptRuntime.java:1690)
    at net.sourceforge.htmlunit.corejs.javascript.Interpreter.interpretLoop(Interpreter.java:1622)
    at net.sourceforge.htmlunit.corejs.javascript.Interpreter.interpret(Interpreter.java:798)
    at net.sourceforge.htmlunit.corejs.javascript.InterpretedFunction.call(InterpretedFunction.java:105)
    at net.sourceforge.htmlunit.corejs.javascript.ContextFactory.doTopCall(ContextFactory.java:405)
    at com.gargoylesoftware.htmlunit.javascript.HtmlUnitContextFactory.doTopCall(HtmlUnitContextFactory.java:309)
    at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3031)
    at net.sourceforge.htmlunit.corejs.javascript.InterpretedFunction.call(InterpretedFunction.java:103)
    at com.gargoylesoftware.htmlunit.javascript.host.EventHandler.call(EventHandler.java:81)
    at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine$4.doRun(JavaScriptEngine.java:609)
    at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine$HtmlUnitContextAction.run(JavaScriptEngine.java:669)
    ... 21 more
Enclosed exception: 
net.sourceforge.htmlunit.corejs.javascript.EcmaError: ReferenceError: "Bootloader" is not defined.
    at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.constructError(ScriptRuntime.java:3603)
    at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.constructError(ScriptRuntime.java:3587)
    at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.notFoundError(ScriptRuntime.java:3657)
    at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.nameOrFunction(ScriptRuntime.java:1749)
    at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.name(ScriptRuntime.java:1690)
    at net.sourceforge.htmlunit.corejs.javascript.Interpreter.interpretLoop(Interpreter.java:1622)
    at script.onclick(onclick event for HtmlDivision[<div class="_119 stat_elem focus_target mtm mbl _5bsm _6dh _51z6" id="u_0_k" data-location="maincolumn" onclick="Bootloader.loadComponents(&quot;ComposerXControllerBootload&quot;, emptyFunction);">] in https://www.facebook.com/?_fb_noscript=1)
    at net.sourceforge.htmlunit.corejs.javascript.Interpreter.interpret(Interpreter.java:798)
    at net.sourceforge.htmlunit.corejs.javascript.InterpretedFunction.call(InterpretedFunction.java:105)
    at net.sourceforge.htmlunit.corejs.javascript.ContextFactory.doTopCall(ContextFactory.java:405)
    at com.gargoylesoftware.htmlunit.javascript.HtmlUnitContextFactory.doTopCall(HtmlUnitContextFactory.java:309)
    at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3031)
    at net.sourceforge.htmlunit.corejs.javascript.InterpretedFunction.call(InterpretedFunction.java:103)
    at com.gargoylesoftware.htmlunit.javascript.host.EventHandler.call(EventHandler.java:81)
    at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine$4.doRun(JavaScriptEngine.java:609)
    at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine$HtmlUnitContextAction.run(JavaScriptEngine.java:669)
    at net.sourceforge.htmlunit.corejs.javascript.Context.call(Context.java:602)
    at net.sourceforge.htmlunit.corejs.javascript.ContextFactory.call(ContextFactory.java:507)
    at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine.callFunction(JavaScriptEngine.java:616)
    at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine.callFunction(JavaScriptEngine.java:591)
    at com.gargoylesoftware.htmlunit.html.HtmlPage.executeJavaScriptFunctionIfPossible(HtmlPage.java:985)
    at com.gargoylesoftware.htmlunit.javascript.host.EventListenersContainer.executeEventHandler(EventListenersContainer.java:210)
    at com.gargoylesoftware.htmlunit.javascript.host.EventListenersContainer.executeBubblingListeners(EventListenersContainer.java:230)
    at com.gargoylesoftware.htmlunit.javascript.host.Node.fireEvent(Node.java:804)
    at com.gargoylesoftware.htmlunit.javascript.host.Node.fireEvent(Node.java:738)
    at com.gargoylesoftware.htmlunit.html.HtmlElement$1.run(HtmlElement.java:869)
    at net.sourceforge.htmlunit.corejs.javascript.Context.call(Context.java:602)
    at net.sourceforge.htmlunit.corejs.javascript.ContextFactory.call(ContextFactory.java:507)
    at com.gargoylesoftware.htmlunit.html.HtmlElement.fireEvent(HtmlElement.java:874)
    at com.gargoylesoftware.htmlunit.html.HtmlElement.doClickFireClickEvent(HtmlElement.java:1311)
    at com.gargoylesoftware.htmlunit.html.HtmlElement.click(HtmlElement.java:1253)
    at com.gargoylesoftware.htmlunit.html.HtmlElement.click(HtmlElement.java:1205)
    at com.gargoylesoftware.htmlunit.html.HtmlElement.dblClick(HtmlElement.java:1351)
    at com.gargoylesoftware.htmlunit.html.HtmlElement.dblClick(HtmlElement.java:1326)
    at prototype.Profile.postLinkOnWall(Profile.java:225)
    at html.Log.findNext(Log.java:150)
    at prototype.Prtp.main(Prtp.java:49)
== CALLING JAVASCRIPT ==
function () {
    [native code, arity=0]
}

======= EXCEPTION END ========

我写的框在普通浏览器上作用于一个不使用 HtmlUnit 执行的重新格式化功能,所以我尝试使用 dbclick() 强制它。

【问题讨论】:

    标签: java javascript htmlunit


    【解决方案1】:

    尝试将您的网络客户端设置为不抛出异常:

    client.getOptions().setThrowExceptionOnScriptError(false);
    

    【讨论】:

    • 我试图修复它而不是逃避异常
    【解决方案2】:

    HtmlUnit 不能很好地与 JavaScript 配合使用。它会经常抛出错误,抱怨未定义的变量或函数。

    从这个意义上说,现实生活浏览器(FireFox、Internet Explorer、Chrome 等)要灵活得多。这意味着它们将允许语法不正确的 HTML 和 JavaScript 片段(例如:不定义函数或不结束 HTML 标记)。

    HtmlUnit 期望一切都(几乎)完美。虽然它会修复一些缺少的结束 HTML 标记,但一般来说,它希望页面中的代码不包含任何类型的错误。此外,即使一切看起来都正确,HtmlUnit 也可能会抱怨。

    您需要考虑的一些事项是:

    • 最重要的是在不同的BrowserVersions之间切换。您可以在创建WebClient 对象时设置它们。事实证明,Internet Explorer(具有讽刺意味的是)在解释 JavaScript 时能给我最好的结果
    • 确保您的 HTML 和 JavaScript 代码都正确
    • 避免使用复杂的库(jQuery似乎得到了适当的支持)
    • 尝试使用非最小化版本的库
    • 如果您碰巧在使用 jQuery(或其他类似库),请避免使用复杂的 jQuery 方法(例如:向元素动态添加事件)

    当然,如果您可以控制从服务器获取的源代码,那么这些 cmets 将适用。有时,情况并非如此。在这种情况下,您的手会更加束缚。

    一种选择是通过以下方式抑制异常:

    webClient.getOptions().setThrowExceptionOnScriptError(false);
    

    虽然,这会让您通过异常,但不会更正任何 JavaScript 错误。这意味着如果抛出此异常的 JS 代码恰好在您的逻辑中至关重要,我的意思是,您绝对依赖于该代码的执行结果,那么您不能让 HtmlUnit 处理您的 JS。如果这恰好是 AJAX 请求的结果,那么您可以自己手动发出请求,而不是让 HtmlUnit 这样做。

    另一方面,如果给你带来麻烦的 JS 代码在你的逻辑中并不重要,我的意思是,它可能只是隐藏一个元素或更改你不关心的颜色,然后抑制异常将是要走的路。

    剩下的选项不多了。

    【讨论】:

    • 我尝试了所有的浏览器,没有一个工作。 “确保您的 HTML 和 JavaScript 代码都是正确的。”我该如何检查?
    • 通过正确编程 JS 代码(例如:不引用未初始化的变量)和标记(例如:关闭所有打开的标签或不在 HTML 4 文档中使用 HTML 5 属性)。 w3c 验证器很可能会帮助您完成最后一个验证器,但我不知道任何验证 JS 代码的工具
    • 与 Java 一起使用的替代方案? HtmlUnit 确实给我带来了很多问题。
    【解决方案3】:

    当我使用方法获得一些网站时,我遇到了同样的问题:

    webClient.getPage("http://somepage.com");
    

    如果您不需要使用 JavaScript 来处理网站,您可以编写:

    webClient.getOptions().setJavaScriptEnabled(false);
    

    在我的情况下,它运行良好并且脚本立即执行(当我只使用 webClient.getOptions().setThrowExceptionOnScriptError(false) 时,脚本总是尝试执行错误的 JavaScript 代码并在控制台中写出异常消息大约 10 秒,所以我不推荐使用它)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-31
      • 1970-01-01
      • 2014-09-05
      • 2023-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多