Как преодолеть исключение HTMLUnit ScriptException?
У меня возникла проблема с строкой кода, которая, вероятно, вызывает некоторые функции js 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("ComposerXControllerBootload", 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("ComposerXControllerBootload", 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().
Ответы
Ответ 1
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-код, который дает вам проблемы, не является критическим в вашей логике, я имею в виду, что он может просто скрывать элемент или изменять цвет, который вам неинтересен, а затем подавлять исключение это будет путь.
Осталось немного вариантов.
Ответ 2
Попробуйте настроить веб-клиента для исключения исключений:
client.getOptions().setThrowExceptionOnScriptError(false);
Ответ 3
У меня была такая же проблема, когда я получил какой-то сайт с методом:
webClient.getPage("http://somepage.com");
Если вам не нужно использовать JavaScript для работы с веб-сайтами, вы можете написать:
webClient.getOptions().setJavaScriptEnabled(false);
В моем случае это работает хорошо, и сценарий выполняется немедленно (когда я использовал только webClient.getOptions().setThrowExceptionOnScriptError(false)
, сценарий всегда пытался выполнить плохой код JavaScript и в течение примерно 10 секунд выписывал сообщения об исключениях в консоли, поэтому я не рекомендую использовать его).