HtmlUnit click() 事件不起作用并在 Java 中触发 ClassCastException
Posted
技术标签:
【中文标题】HtmlUnit click() 事件不起作用并在 Java 中触发 ClassCastException【英文标题】:HtmlUnit click() event does not work and triggers ClassCastException in Java 【发布时间】:2017-09-09 16:58:22 【问题描述】:我在 Java 应用程序中使用 htmlUnit 来加载网页并提交其表单。我毫无问题地获得了表单和提交输入,但是当我在该元素上调用函数 click() 时,它触发了 Cast Exception 并且似乎没有执行 click 事件。这是我的 webClient 配置:
this.webClient = new WebClient(BrowserVersion.CHROME);
webClient.getOptions().setjavascriptEnabled(true);
webClient.getOptions().setThrowExceptionOnScriptError(true);
webClient.getOptions().setCssEnabled(false);
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getOptions().setRedirectEnabled(true);
final HtmlPage jobPage = webClient.getPage("https://mySite/j#edit-job?id="+job.getJobID());
webClient.waitForBackgroundJavaScript(15000);
这是页面加载和输入选择的代码:
HtmlForm form = jobPage.getFormByName("");
HtmlSubmitInput submit = null;
final List<HtmlInput> inputs = form.getInputsByName("");
for(HtmlInput input : inputs)
if(input.getAttribute("id").equals("postFormSubmit"))
submit = (HtmlSubmitInput)input;
break;
if(submit != null)
try
HtmlPage confirmUpdate = submit.click();
webClient.waitForBackgroundJavaScript(15000);
System.out.println("response : \n\n");
System.out.println(confirmUpdate.asText());
System.out.println("end response");
catch(Exception e)
e.printStackTrace();
else
System.out.println("submit input non trouvé");
我还尝试通过以下方式手动执行一些 javascript:
jobPage.executeJavascript("javascript:document.getElementById('postFormSubmit').click();");
但我得到了同样的例外:
INFOS: Caught script exception
======= EXCEPTION START ========
Exception class=[java.lang.ClassCastException]
com.gargoylesoftware.htmlunit.ScriptException: com.gargoylesoftware.htmlunit.javascript.host.html.HTMLInputElement cannot be cast to com.gargoylesoftware.htmlunit.html.HtmlElement
at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine$HtmlUnitContextAction.run(JavaScriptEngine.java:898)
at net.sourceforge.htmlunit.corejs.javascript.Context.call(Context.java:637)
at net.sourceforge.htmlunit.corejs.javascript.ContextFactory.call(ContextFactory.java:518)
at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine.callFunction(JavaScriptEngine.java:827)
at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine.callFunction(JavaScriptEngine.java:799)
at com.gargoylesoftware.htmlunit.html.HtmlPage.executeJavaScriptFunctionIfPossible(HtmlPage.java:2470)
at com.gargoylesoftware.htmlunit.javascript.host.event.EventListenersContainer.executeEventListeners(EventListenersContainer.java:259)
at com.gargoylesoftware.htmlunit.javascript.host.event.EventListenersContainer.executeBubblingListeners(EventListenersContainer.java:325)
at com.gargoylesoftware.htmlunit.javascript.host.event.EventTarget.fireEvent(EventTarget.java:188)
at com.gargoylesoftware.htmlunit.html.DomElement$2.run(DomElement.java:1389)
at net.sourceforge.htmlunit.corejs.javascript.Context.call(Context.java:637)
at net.sourceforge.htmlunit.corejs.javascript.ContextFactory.call(ContextFactory.java:518)
at com.gargoylesoftware.htmlunit.html.DomElement.fireEvent(DomElement.java:1394)
at com.gargoylesoftware.htmlunit.html.DomElement.fireEvent(DomElement.java:1362)
at com.gargoylesoftware.htmlunit.html.HtmlForm.submit(HtmlForm.java:116)
at com.gargoylesoftware.htmlunit.html.HtmlSubmitInput.doClickStateUpdate(HtmlSubmitInput.java:90)
at com.gargoylesoftware.htmlunit.html.DomElement.click(DomElement.java:999)
at com.gargoylesoftware.htmlunit.html.DomElement.click(DomElement.java:944)
at com.gargoylesoftware.htmlunit.html.DomElement.click(DomElement.java:884)
at com.gargoylesoftware.htmlunit.html.DomElement.click(DomElement.java:865)
at model.IndeedManip$2.run(IndeedManip.java:309)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.runAndReset(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassCastException: com.gargoylesoftware.htmlunit.javascript.host.html.HTMLInputElement cannot be cast to com.gargoylesoftware.htmlunit.html.HtmlElement
at com.gargoylesoftware.htmlunit.javascript.host.dom.AbstractList.addElementIds(AbstractList.java:541)
at com.gargoylesoftware.htmlunit.javascript.host.dom.AbstractList.getIds(AbstractList.java:523)
at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.enumChangeObject(ScriptRuntime.java:2235)
at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.enumInit(ScriptRuntime.java:2136)
at net.sourceforge.htmlunit.corejs.javascript.Interpreter.interpretLoop(Interpreter.java:1740)
at net.sourceforge.htmlunit.corejs.javascript.Interpreter.interpret(Interpreter.java:800)
at net.sourceforge.htmlunit.corejs.javascript.InterpretedFunction.call(InterpretedFunction.java:105)
at net.sourceforge.htmlunit.corejs.javascript.NativeArray.iterativeMethod(NativeArray.java:1694)
at net.sourceforge.htmlunit.corejs.javascript.NativeArray.execIdCall(NativeArray.java:405)
at net.sourceforge.htmlunit.corejs.javascript.IdFunctionObject.call(IdFunctionObject.java:94)
at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.applyOrCall(ScriptRuntime.java:2575)
at net.sourceforge.htmlunit.corejs.javascript.BaseFunction.execIdCall(BaseFunction.java:321)
at net.sourceforge.htmlunit.corejs.javascript.IdFunctionObject.call(IdFunctionObject.java:94)
at net.sourceforge.htmlunit.corejs.javascript.Interpreter.interpretLoop(Interpreter.java:1540)
at net.sourceforge.htmlunit.corejs.javascript.Interpreter.interpret(Interpreter.java:800)
at net.sourceforge.htmlunit.corejs.javascript.InterpretedFunction.call(InterpretedFunction.java:105)
at net.sourceforge.htmlunit.corejs.javascript.NativeArray.iterativeMethod(NativeArray.java:1694)
at net.sourceforge.htmlunit.corejs.javascript.NativeArray.execIdCall(NativeArray.java:405)
at net.sourceforge.htmlunit.corejs.javascript.IdFunctionObject.call(IdFunctionObject.java:94)
at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.applyOrCall(ScriptRuntime.java:2575)
at net.sourceforge.htmlunit.corejs.javascript.BaseFunction.execIdCall(BaseFunction.java:321)
at net.sourceforge.htmlunit.corejs.javascript.IdFunctionObject.call(IdFunctionObject.java:94)
at net.sourceforge.htmlunit.corejs.javascript.Interpreter.interpretLoop(Interpreter.java:1540)
at net.sourceforge.htmlunit.corejs.javascript.Interpreter.interpret(Interpreter.java:800)
at net.sourceforge.htmlunit.corejs.javascript.InterpretedFunction.call(InterpretedFunction.java:105)
at net.sourceforge.htmlunit.corejs.javascript.ContextFactory.doTopCall(ContextFactory.java:416)
at com.gargoylesoftware.htmlunit.javascript.HtmlUnitContextFactory.doTopCall(HtmlUnitContextFactory.java:292)
at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3264)
at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine$4.doRun(JavaScriptEngine.java:820)
at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine$HtmlUnitContextAction.run(JavaScriptEngine.java:883)
... 27 more
Enclosed exception:
java.lang.ClassCastException: com.gargoylesoftware.htmlunit.javascript.host.html.HTMLInputElement cannot be cast to com.gargoylesoftware.htmlunit.html.HtmlElement
at com.gargoylesoftware.htmlunit.javascript.host.dom.AbstractList.addElementIds(AbstractList.java:541)
at com.gargoylesoftware.htmlunit.javascript.host.dom.AbstractList.getIds(AbstractList.java:523)
at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.enumChangeObject(ScriptRuntime.java:2235)
at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.enumInit(ScriptRuntime.java:2136)
at net.sourceforge.htmlunit.corejs.javascript.Interpreter.interpretLoop(Interpreter.java:1740)
at net.sourceforge.htmlunit.corejs.javascript.Interpreter.interpret(Interpreter.java:800)
at net.sourceforge.htmlunit.corejs.javascript.InterpretedFunction.call(InterpretedFunction.java:105)
at net.sourceforge.htmlunit.corejs.javascript.NativeArray.iterativeMethod(NativeArray.java:1694)
at net.sourceforge.htmlunit.corejs.javascript.NativeArray.execIdCall(NativeArray.java:405)
at net.sourceforge.htmlunit.corejs.javascript.IdFunctionObject.call(IdFunctionObject.java:94)
at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.applyOrCall(ScriptRuntime.java:2575)
at net.sourceforge.htmlunit.corejs.javascript.BaseFunction.execIdCall(BaseFunction.java:321)
at net.sourceforge.htmlunit.corejs.javascript.IdFunctionObject.call(IdFunctionObject.java:94)
at net.sourceforge.htmlunit.corejs.javascript.Interpreter.interpretLoop(Interpreter.java:1540)
at net.sourceforge.htmlunit.corejs.javascript.Interpreter.interpret(Interpreter.java:800)
at net.sourceforge.htmlunit.corejs.javascript.InterpretedFunction.call(InterpretedFunction.java:105)
at net.sourceforge.htmlunit.corejs.javascript.NativeArray.iterativeMethod(NativeArray.java:1694)
at net.sourceforge.htmlunit.corejs.javascript.NativeArray.execIdCall(NativeArray.java:405)
at net.sourceforge.htmlunit.corejs.javascript.IdFunctionObject.call(IdFunctionObject.java:94)
at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.applyOrCall(ScriptRuntime.java:2575)
at net.sourceforge.htmlunit.corejs.javascript.BaseFunction.execIdCall(BaseFunction.java:321)
at net.sourceforge.htmlunit.corejs.javascript.IdFunctionObject.call(IdFunctionObject.java:94)
at net.sourceforge.htmlunit.corejs.javascript.Interpreter.interpretLoop(Interpreter.java:1540)
at net.sourceforge.htmlunit.corejs.javascript.Interpreter.interpret(Interpreter.java:800)
at net.sourceforge.htmlunit.corejs.javascript.InterpretedFunction.call(InterpretedFunction.java:105)
at net.sourceforge.htmlunit.corejs.javascript.ContextFactory.doTopCall(ContextFactory.java:416)
at com.gargoylesoftware.htmlunit.javascript.HtmlUnitContextFactory.doTopCall(HtmlUnitContextFactory.java:292)
at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3264)
at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine$4.doRun(JavaScriptEngine.java:820)
at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine$HtmlUnitContextAction.run(JavaScriptEngine.java:883)
at net.sourceforge.htmlunit.corejs.javascript.Context.call(Context.java:637)
at net.sourceforge.htmlunit.corejs.javascript.ContextFactory.call(ContextFactory.java:518)
at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine.callFunction(JavaScriptEngine.java:827)
at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine.callFunction(JavaScriptEngine.java:799)
at com.gargoylesoftware.htmlunit.html.HtmlPage.executeJavaScriptFunctionIfPossible(HtmlPage.java:2470)
at com.gargoylesoftware.htmlunit.javascript.host.event.EventListenersContainer.executeEventListeners(EventListenersContainer.java:259)
at com.gargoylesoftware.htmlunit.javascript.host.event.EventListenersContainer.executeBubblingListeners(EventListenersContainer.java:325)
at com.gargoylesoftware.htmlunit.javascript.host.event.EventTarget.fireEvent(EventTarget.java:188)
at com.gargoylesoftware.htmlunit.html.DomElement$2.run(DomElement.java:1389)
at net.sourceforge.htmlunit.corejs.javascript.Context.call(Context.java:637)
at net.sourceforge.htmlunit.corejs.javascript.ContextFactory.call(ContextFactory.java:518)
at com.gargoylesoftware.htmlunit.html.DomElement.fireEvent(DomElement.java:1394)
at com.gargoylesoftware.htmlunit.html.DomElement.fireEvent(DomElement.java:1362)
at com.gargoylesoftware.htmlunit.html.HtmlForm.submit(HtmlForm.java:116)
at com.gargoylesoftware.htmlunit.html.HtmlSubmitInput.doClickStateUpdate(HtmlSubmitInput.java:90)
at com.gargoylesoftware.htmlunit.html.DomElement.click(DomElement.java:999)
at com.gargoylesoftware.htmlunit.html.DomElement.click(DomElement.java:944)
at com.gargoylesoftware.htmlunit.html.DomElement.click(DomElement.java:884)
at com.gargoylesoftware.htmlunit.html.DomElement.click(DomElement.java:865)
at model.IndeedManip$2.run(IndeedManip.java:309)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.runAndReset(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
== CALLING JAVASCRIPT ==
function (c)
return a.call(b.src, b.Mh, c);
======= EXCEPTION END ========
据说这是一个强制转换异常,但我没有进行任何强制转换,错误位于click()
事件的行。
如果您知道使用 HtmlUnit 触发点击事件的另一种方法,请告诉我。
【问题讨论】:
在哪一行代码上抛出异常? 这个:HtmlPage confirmUpdate = submit.click(); 在您使用它的页面上,该按钮如何提交?它是调用 Javascript 函数还是通过 HTML 提交? 请使用最新版本,并提供您的完整案例(附网址) 请阅读Under what circumstances may I add “urgent” or other similar phrases to my question, in order to obtain faster answers? - 总结是这不是解决志愿者的理想方式,并且可能会适得其反。请不要将此添加到您的问题中。 【参考方案1】:这刚刚通过提交 14092 和 14093 修复。
您可以从here 获取最新版本。
测试用例是:
/**
* @throws Exception on test failure
*/
@Test
@Alerts(DEFAULT = "0,1,2,3,4,5,entries,forEach,item,keys,length,values",
IE = "0,1,2,3,4,5,item,length")
public void iterator() throws Exception
final String html = "<html><head><title>test</title>\n"
+ "<script>\n"
+ " function test() \n"
+ " var all = [];\n"
+ " for (var i in document.querySelectorAll('*')) \n"
+ " all.push(i);\n"
+ " \n"
+ " all.sort(sortFunction);\n"
+ " alert(all);\n"
+ " \n"
+ " function sortFunction(s1, s2) \n"
+ " return s1.toLowerCase() > s2.toLowerCase() ? 1 : -1;\n"
+ " \n"
+ "</script>\n"
+ "</head><body onload='test()'>\n"
+ " <div>/div>\n"
+ "</body></html>";
loadPageWithAlerts2(html);
【讨论】:
非常感谢!不再抛出异常,但由于某些原因,我的表单仍未提交......当我执行click()
事件时,它只会刷新页面......你知道这可能来自哪里吗?如果网站检测到我们正在使用 java,或者 java 无法编译每个异步调用?
顺便说一下,我在网页上检测到一条消息,告诉我“正在加载...服务器错误,请稍后再试抱歉!您似乎处于隐私浏览模式,这不支持。请切换浏览器模式。”。你知道为什么吗?提前致谢【参考方案2】:
感谢 Ahmed Ashour,此函数不再触发异常,但 HtmlUnit 从未提交过我的表单。
最后我改用 Selenium,它对 javascript 的执行效率更高。我建议任何从事 Web 抓取应用程序的人,该应用程序提交 ajax 驱动的表单以使用 Selenium
【讨论】:
以上是关于HtmlUnit click() 事件不起作用并在 Java 中触发 ClassCastException的主要内容,如果未能解决你的问题,请参考以下文章
Java HtmlUnit 单击锚链接不起作用。如何获取新页面?