首页 > 解决方案 > 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());
        }
    }

我期待返回一个成功的查询。

标签: javahtmlunit

解决方案


让我们从一般的东西开始:

对于客户端的设置,请仅设置您真正需要的选项。默认是像真正的浏览器一样运行,不需要启用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 年前引入了一个奇怪的错误),该错误现已修复。

希望有帮助。


推荐阅读