簡體   English   中英

如何克服 HTMLUnit ScriptException?

[英]How to overcome an HTMLUnit ScriptException?

我的一行代碼有問題,可能會觸發一些 js function e couse 一個異常,我該如何解決這個問題?

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 ========

我寫的框在普通瀏覽器上運行重新格式化 function,這不是使用 HtmlUnit 執行的,所以我試圖用 dbclick() 強制它。

HtmlUnit在JavaScript中不能很好地發揮作用。 它將經常拋出錯誤,抱怨未定義的變量或函數。

從這種意義上說, 現實生活中的瀏覽器(FireFox,Internet Explorer,Chrome等)更加靈活。 這意味着它們將允許使用語法上不正確的HTML和JavaScript(例如:不定義函數或不結束HTML標簽)。

HtmlUnit期望一切(幾乎)完美。 雖然,它將修復一些丟失的結尾HTML標記,但通常,它希望頁面中的代碼不包含任何類型的錯誤。 此外,即使一切看起來正確,HtmlUnit甚至可能會抱怨。

您需要考慮的一些事項是:

  • 最重要的一個是在不同的BrowserVersions之間切換。 您可以在創建WebClient對象時進行設置。 事實證明,Internet Explorer(具有諷刺意味的)可以為我帶來最好的解釋JavaScript的效果
  • 確保您的HTML和JavaScript代碼都正確
  • 避免使用復雜的庫(似乎已正確支持jQuery)
  • 嘗試使用非最小化版本的庫
  • 如果您碰巧正在使用jQuery(或其他類似的庫),請避免使用復雜的jQuery方法(例如:將事件動態添加到元素)

當然,如果您可以控制從服務器獲取的源代碼,這些注釋將適用。 有時情況並非如此。 在這種情況下,您的雙手會更綁。

一種選擇是使用以下方法抑制異常:

webClient.getOptions().setThrowExceptionOnScriptError(false);

雖然,這將使您度過異常,不會糾正任何JavaScript錯誤。 這意味着,如果引發此異常的JS代碼對您的邏輯至關重要,我的意思是,您絕對依賴於該代碼的執行結果,那么您將無法讓HtmlUnit處理您的JS。 如果這恰巧是AJAX請求的結果,那么您可以自己手動發出請求,而不是讓HtmlUnit發出。

另一方面,如果給您帶來麻煩的JS代碼在您的邏輯中並不重要,我的意思是,這可能只是隱藏一個元素或更改了您不關心的顏色,那么抑制異常將是要走的路。

剩下的選擇不多了。

嘗試將您的Web客戶端設置為不引發異常:

client.getOptions().setThrowExceptionOnScriptError(false);

只是為了在傷口上撒鹽。 HTMLUnit 遠遠落后於現代瀏覽器標准。 Atm 僅支持 ES2015 的一小部分。 問題在於底層的 javascript 引擎 (Rhino) 的發展速度不夠快。 如果您想留在 java realm 進行測試,我建議您認真查看 Selenium Webdrivers 並在無頭模式下使用 chrome 作為引擎。 這不再是純粹的 java 解決方案,而是使用最新的引擎。 直到 HTMLUnit 切換到不同的引擎,和/或 Rhino 一起行動 HTML 單元絕對不推薦用於 javascript 單元測試。

當我使用方法獲得一些網站時,我遇到了同樣的問題:

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

如果您不需要使用JavaScript來處理網站,則可以編寫:

webClient.getOptions().setJavaScriptEnabled(false);

就我而言,它運行良好並且腳本立即執行(當我僅使用webClient.getOptions().setThrowExceptionOnScriptError(false) ,腳本始終嘗試執行錯誤的JavaScript代碼,並在控制台中寫出大約10秒鍾的異常消息,所以我不建議使用它)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM