【问题标题】:htmlUnit - Is it possible to execute only specific JS functions?htmlUnit - 是否可以只执行特定的 JS 函数?
【发布时间】:2019-05-22 11:30:37
【问题描述】:

我有一个问题 - 我正在尝试抓取电影网页, ---> https://cinemaxx.dk/koebenhavn

我需要获取有关保留/售出多少座位的数据,我需要提取最后一个快照。

预留/出售的座位在图片上显示为红色方块:

基本上,我的逻辑是这样的。

  1. 我使用 htmlUnit 抓取联系人。
  2. 我设置htmlUnit执行所有JS。
  3. 提取(reservedSeats BASE64 字符串)。
  4. 将 BASE64 字符串转换为图像。
  5. 然后我的程序分析图像,并计算保留/售出的座位数。

    • 我的问题是:

因为我需要图片的最后一张快照,因为这张图片提供了与预留/售出的座位数量相关的正确数据。 - 我在电影开始前 3 分钟开始抓取网站,...直到 input == null。

我通过循环我的抓取方法来做到这一点 - 但是 ciname 服务器会在每个请求时自动保留 2 个席位(并将它们保留 10 分钟)。 - 所以我最终保留了整个电影院的所有座位...(您可以在上图中的 2 个保留座位(蓝色方块)上看到一个示例)。

我在 HTML 中找到了根据请求保留 2 个席位的 JS 方法 - 现在我希望 htmlUnit 执行所有 JS 执行这个通过 HTTP 请求保留这些 2 个席位的 JS 方法。

  • 我希望它有道理,以上所有。

  • 有没有人可以带领我朝着正确的方向前进?或者可能有类似的问题?

public void scraper(String url) {

    final String URL = url;

    //Initialize Ghost Browser (FireFox_60):
    try (final WebClient webClient = new WebClient(BrowserVersion.FIREFOX_60)) {

        //Configure Ghost Browser:
        webClient.getOptions().setJavaScriptEnabled(true);
        webClient.getOptions().setThrowExceptionOnScriptError(false);
        webClient.getOptions().setCssEnabled(false);

        //Load Url & Configure Ghost Browser:
        final HtmlPage page = webClient.getPage(URL);
        webClient.setAjaxController(new NicelyResynchronizingAjaxController());
        webClient.waitForBackgroundJavaScript(3000);


        //Spider JS PATH to BASE64 data:
        final HtmlElement seatPictureRaw = page.querySelector
                ("body > div.page.page--booking.ng-scope > div.relative > div.inner__container.inner__container--content " +
                        "> div.seatselect > div > div > div > div:nth-child(2) > div.seatselect__image > img");

        //Terminate Current web session:
        webClient.getCurrentWindow().getJobManager().removeAllJobs();
        webClient.close();


        //Process the raw BASE64 Data - Extract clean BASE64 String:
        String rawBASE64Data = String.valueOf(seatPictureRaw);
        String[] arrOfStr = rawBASE64Data.split("(?<=> 0\") ");
        String cleanedUpBASE64Data = arrOfStr[1];
        String cleanedUpBASE64Data1 = cleanedUpBASE64Data.replace("src=\"data:image/gif;base64,", "");
        String cleanedUpBASE64Data2 = cleanedUpBASE64Data1.replace("\">]", "");
        //System.out.println(cleanedUpBASE64Data2);


        //Decode BASE64 Rawdata to Image:
        final byte[] decodedBytes = Base64.getDecoder().decode(cleanedUpBASE64Data2);
        System.out.println("Numbers Of Caracters in BASE64 String: " + decodedBytes.length);
        BufferedImage image = ImageIO.read(new ByteArrayInputStream(decodedBytes));

        //Forward image for PictureAnalyzer Class...
        final PictureAnalyzer pictureAnalyzer = new PictureAnalyzer();
        pictureAnalyzer.analyzePixels(image);

    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

【问题讨论】:

  • 那不是 Flash 应用吗..?
  • @Teemu - 呃,你到底是什么意思?网站?
  • 您需要启用 javascript 才能获取图形 - 对吧?
  • 请先清理你的代码;在做任何其他事情之前配置客户端是有意义的 - 将所有 webClient.getOptions() 语句移到顶部
  • 通常 webClient.setAjaxController(new NicelyResynchronizingAjaxController());不需要你真的需要这个吗?

标签: java web-scraping htmlunit


【解决方案1】:

您有一个选择是拦截和修改服务器响应并用其他东西替换函数调用。

  • 只替换函数名(这很丑,因为它会在运行时生成一个 js 异常)或
  • 从源中删除函数调用或
  • 将函数体替换为 {} 或
  • ....

更多信息请见http://htmlunit.sourceforge.net/faq.html#HowToModifyRequestOrResponse

【讨论】:

  • 我不确定你所说的“noop”是什么意思?。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多