java - htmlunit:发送 POST 表单并检索响应
问题描述
网站:http ://www.sunat.gob.pe/cl-ti-itmrconsruc/jcrS00Alias 它有2个框架,
一个带有 POST 表单的: http: //www.sunat.gob.pe/cl-ti-itmrconsruc/frameCriterioBusqueda.jsp
和显示结果的另一个框架:http: //www.sunat.gob.pe/cl-ti-itmrconsruc/frameResultadoBusqueda.html
在 Apache Netbeans 中测试给我一个错误:
--- exec-maven-plugin:1.5.0:exec (default-cli) @ htmunit --- 2019 年 9 月 30 日晚上 8:39:15 com.gargoylesoftware.htmlunit.IncorrectnessListenerImpl 通知 ADVERTENCIA:遇到过时的内容类型:'应用程序/x-javascript'。2019 年 9 月 30 日晚上 8:39:21 com.gargoylesoftware.htmlunit.IncorrectnessListenerImpl 通知广告:遇到过时的内容类型:'application/x-javascript'。2019 年 9 月 30 日晚上 8:39:21 com.gargoylesoftware.htmlunit.javascript.DefaultJavaScriptErrorListener scriptException GRAVE:JavaScript 执行期间出错 ======= EXCEPTION START ======== EcmaError: lineNumber=[0] column=[0] lineSource=[function () {] name=[TypeError] sourceName=[在http://www.sunat.gob.pe/cl-ti-itmrconsruc/jcrS00Alias中为 HtmlBody[] 加载事件]message = [TypeError:无法调用未定义的方法“goRefresh”] com.gargoylesoftware.htmlunit.ScriptException:TypeError:无法调用未定义的方法“goRefresh”
我的预付款:
public static void main(String[] args) {
// TODO code application logic here
try {
String url = "http://www.sunat.gob.pe/cl-ti-itmrconsruc/frameCriterioBusqueda.jsp";
final WebClient webClient = new WebClient(BrowserVersion.CHROME);
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getOptions().setCssEnabled(false);
webClient.getCookieManager().setCookiesEnabled(true);
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
webClient.getOptions().setThrowExceptionOnScriptError(false);
HtmlPage htmlpage = webClient.getPage(url);
//webClient.waitForBackgroundJavaScript(10000);
//CookieManager coo = webClient.getCookieManager();
//Cookie cookie = coo.getCookie("TS01c75c6f");
//System.out.println(cookie.getValue());
HtmlForm htmlForm = htmlpage.getElementByName("mainForm");
//htmlForm.setActionAttribute("jcrS00Alias");
HtmlTextInput input1 = htmlForm.getInputByName("search1");
HtmlTextInput input2 = htmlForm.getInputByName("codigo");
input1.setText("10468790497");
HtmlHiddenInput hidden = (HtmlHiddenInput)htmlForm.getInputByName("accion");
hidden.setValueAttribute("consPorRuc");
HtmlImage image = htmlpage.<HtmlImage>getFirstByXPath("//img[@src='captcha?accion=image']");
ImageReader img = image.getImageReader();
BufferedImage buf = img.read(0);
// Show image
ImageIcon icon = new ImageIcon(buf);
String codigo = JOptionPane.showInputDialog(null, icon, "Captcha image", JOptionPane.PLAIN_MESSAGE);
input2.setText(codigo);
HtmlButton boton = (HtmlButton) htmlpage.createElement("button");
boton.setAttribute("type", "submit");
htmlForm.appendChild(boton);
htmlpage = boton.click();
System.out.println(htmlpage.asXml().toString());
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
我期待返回一个成功的查询。
解决方案
让我们从一般的东西开始:
对于客户端的设置,请仅设置您真正需要的选项。默认是像真正的浏览器一样运行,不需要启用cookies。
有一些警告你可以忽略
无法调用未定义的方法“goRefresh”
这是因为框架中的 js(在您的情况下为结果框架文档)试图从另一个框架调用一个函数,以更新验证码。但是您没有加载整个框架集 - 因此无法以预期的方式访问该功能。
为了获得结果,您必须获得另一帧的内容。
这段代码似乎工作:
// work with the whole frameset
String url = "http://www.sunat.gob.pe/cl-ti-itmrconsruc/jcrS00Alias";
try (final WebClient webClient = new WebClient(BrowserVersion.FIREFOX_60)) {
// do not stop in case of js errors
webClient.getOptions().setThrowExceptionOnScriptError(false);
HtmlPage frameset = webClient.getPage(url);
HtmlPage searchPage = (HtmlPage) frameset.getFrameByName("leftFrame").getEnclosedPage();
HtmlForm htmlForm = searchPage.getElementByName("mainForm");
// set search field
HtmlTextInput input1 = htmlForm.getInputByName("search1");
input1.setText("10468790497");
// process captcha
HtmlImage image = searchPage.<HtmlImage>getFirstByXPath("//img[@src='captcha?accion=image']");
ImageReader img = image.getImageReader();
BufferedImage buf = img.read(0);
ImageIcon icon = new ImageIcon(buf);
String codigo = JOptionPane.showInputDialog(null, icon, "Captcha image", JOptionPane.PLAIN_MESSAGE);
HtmlTextInput input2 = htmlForm.getInputByName("codigo");
input2.setText(codigo);
// click the button
HtmlElement boton = htmlForm.getElementsByAttribute("input", "value", "Buscar").get(0);
boton.click();
// and get the result
HtmlPage resultPage = (HtmlPage) frameset.getFrameByName("mainFrame").getEnclosedPage();
System.out.println(resultPage.asText());
}
但是您需要最新的 HtmlUnit 快照才能运行它而不会出现 js 错误(10 年前引入了一个奇怪的错误),该错误现已修复。
希望有帮助。
推荐阅读
- javascript - React - 如何访问自动完成的结果
- php - Laravel PasswordBroker::createToken() 必须实现接口
- pyspark - 使用 Pyspark 将格式 MMM d yyyy hh:mm AM/PM 的字符串转换为日期
- python - 从 python 运行管道 bash commnads
- javascript - 将多个 PHP 变量发送到 javascript 函数
- java - 当设备与 USB 端口连接时如何通知 android 应用程序
- r - 获取列表中不包含任何 NA 的元素的索引
- c# - DisallowNull 用于方法参数
- c# - 在不使用进程事件的情况下确定文件何时不再使用
- javascript - useState 不保存数据