2

我正在尝试使用 HTMLUnit 来生成我们的 ajax 页面的可抓取 HTML 快照(如https://developers.google.com/webmasters/ajax-crawling/所建议的那样)。这个想法是创建允许企业通过定期计划服务或按照自己的意愿创建快照的功能。

我写了一个快速的 POC 主类来测试理论,它按预期工作(当我们查看源代码时,我们可以看到我们以前看不到的谷歌爬虫所需的所有数据)。我现在将其集成到我们在 Tomcat 7 上运行的应用程序中,我在从 Google 下载 jquery.js 时遇到问题,其中包含以下日志消息

2013-03-15 18:10:38,071 ERROR [author->taskExecutor-1] com.gargoylesoftware.htmlunit.html.HtmlPage       : Error loading JavaScript from [https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js].
javax.net.ssl.SSLException: hostname in certificate didn't match: <ajax.googleapis.com/173.194.67.95> != <*.googleapis.com> OR <*.googleapis.com> OR <googleapis.com>
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:228)
at org.apache.http.conn.ssl.BrowserCompatHostnameVerifier.verify(BrowserCompatHostnameVerifier.java:54)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:149)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:130)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:397)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:495)
at org.apache.http.conn.scheme.SchemeSocketFactoryAdaptor.connectSocket(SchemeSocketFactoryAdaptor.java:62)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:148)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:150)

...

因此,ajax 没有被执行,并且快照不包含我们希望的视图源中的数据。有谁知道为什么这会发生在我的 Tomcat 代码版本中而不是我的独立主类中?这两个版本都在我的本地机器上运行,一个只是在 Tomcat (v7) 中,一个是 Java 应用程序。两个版本都有相同的 Maven 包含(见底部)。

注意:我已经尝试在实例化时指定 BrowserVersion,WebClient client = new WebClient(BrowserVersion.FIREFOX_17);因为我确实读过这会产生更好的结果(对不起,我不记得链接了)。再次,这在 POC 中运行良好,但是当我在 Tomcat II 中运行它时,会看到日志“Instatiating Web Client”,但无论我等待多长时间,它都不会到达“Client Instatiated”或抛出任何异常。我不知道这是否与无法下载 jqeury.js 有关,因为它仍然可以在没有指定 BrowserVersion 的 POC 中工作。

这是我的 POC Java 主要方法

        OutputStreamWriter writer = null;

        try {
            final WebClient webClient = new WebClient();
            webClient.getOptions().setThrowExceptionOnScriptError(false);
            webClient.getOptions().setPrintContentOnFailingStatusCode(false);
            final HtmlPage page = (HtmlPage)webClient.getPage("http://myurl.com");

            webClient.waitForBackgroundJavaScript(1500);

            File file = new File("C:\\test.html");
            FileUtils.touch(file);

            writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
            writer.write(page.asXml());
            writer.flush();

        } catch (MalformedURLException mue) {
            System.out.println("MalformedURL exception");
        } catch (IOException ioe) {
            System.out.println("IOException occurred " +  ioe.getMessage());
        } finally {
            IOUtils.closeQuietly(writer);
        }

这是我的集成版本

        /* Entry point for the generation */
     public void generate() {

        log.info("Beginning snapshot generation...");

        try {

            // Get the URLS
            log.info("Retrieving list of page urls");
            List<String> pageUrls = getUrlList();
            log.info("Found {} urls to generate", pageUrls.size());

            // For every url we have generate a snapshot
            for (String pageUrl: pageUrls) {
                takeSnapshot(pageUrl);
            }
            log.info("Finished generating snapshots!");
        } catch (Exception e) {
            log.error("Exception caught while generating snapshot", e);
        }
    }

    /**
     * Take the HTML snapshot of the url and output to the snapshot directory
     */
    private void takeSnapshot(String pagePath) {
        try {
            String fullOutputFilePath = config.getHtmlSnapshotDirectory() + File.separator
                                                        + pagePath + File.separator + HTML_SNAPSHOT_FILE_NAME;
            String pageUrl = "http://myurl.com" + pagePath;

            log.debug("Instantiating Web Client...");
            final WebClient webClient = new WebClient();
            log.debug("Client instantiated");
            webClient.getOptions().setThrowExceptionOnScriptError(false);
            webClient.getOptions().setPrintContentOnFailingStatusCode(false);
            final HtmlPage page = (HtmlPage)webClient.getPage(pageUrl);

            webClient.waitForBackgroundJavaScript(1500);

            snapshotFile = new File(fullOutputFilePath);
            FileUtils.touch(snapshotFile);

            writer = new OutputStreamWriter(new FileOutputStream(snapshotFile), "UTF-8");
            writer.write(page.asXml());
            writer.flush();
        } catch (MalformedURLException mue) {
            System.out.println("MalformedURL exception");
        } catch (IOException ioe) {
            System.out.println("IOException occurred " +  ioe.getMessage());
        } finally {
            IOUtils.closeQuietly(writer);
        }
    }

Maven 依赖项

        <dependency>
            <groupId>net.sourceforge.htmlunit</groupId>
            <artifactId>htmlunit</artifactId>
            <version>2.12</version>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.2.3</version>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.3-alpha1</version>
        </dependency>

感谢大家!!!

4

1 回答 1

1

所以添加webClient.getOptions().setUseInsecureSSL(true);是解决这个问题的关键。但是,我不得不使用已弃用的版本webClient.setUseInsecureSSL(true);

我不知道为什么新版本在 Tomcat 中运行时不起作用,但它解决了这个问题。如果有人可以提供洞察力,为什么那会很棒。我仍然不知道为什么在运行 Tomcat 时设置 BrowserVersion 会导致应用程序停止。我已经向 HtmlUnit 邮件列表询问了这些问题的答案。

于 2013-03-19T12:35:44.377 回答