htmlUnit-是否可以仅执行特定的JS函数?

时间:2019-05-22 11:30:38

标签: java web-scraping htmlunit

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

我需要获取有关已预订/已售出座位数的数据,我需要提取最后一个快照。

保留/出售的座位在图片上显示为红色正方形:

enter image description here

很容易地,我的逻辑是这样。

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

    • 我的问题是:

由于我需要这张照片的最后一张快照,-原因是这张照片给出了与保留/售出的座位数有关的正确数据。 -我在电影开始前3分钟开始抓取网站,...直到输入== null。

我通过循环我的scrape方法来做到这一点-但是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();
    }
}

1 个答案:

答案 0 :(得分:0)

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

  • 仅替换函数名称(这很麻烦,因为它将在运行时生成js异常)或
  • 从源代码中删除函数调用,或者
  • 用{}或
  • 替换功能主体
  • ....

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