【问题标题】:How to scrape the price from dynamically updated webpages?如何从动态更新的网页中获取价格?
【发布时间】:2020-08-12 19:34:00
【问题描述】:

我在尝试从动态更新的网页中获取价格时遇到问题。我的意思是使用 UrlConnection、Jsoup、HtmlUnit 等方式没有收到大部分 html 代码。 我不太了解网络抓取,但我想这个问题是这样的互联网商店: Auchan, Silpo 使用 javascript 和 ajax 加载有关产品的主要信息。在我看来,问题在于重定向或延迟,它不允许获取包含所有需要数据的完整加载的 html 文件。 那么,问题是如何从上面的链接中获取价格?

我已经尝试了几种方法:

  1. 网址连接

        URL url;
        try {
            url = new URL("https://auchan.ua/govjadina-v-kartofel-nom-pjure-so-svekloj-hipp-6440-220-g-297668/");
            URLConnection con = url.openConnection();
            InputStream is = con.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String line;
            try(FileWriter fileWriter = new FileWriter("output.html")){
                while ((line = br.readLine()) != null) {
                    fileWriter.write(line+"\n");
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    

    运行良好,但返回没有价格数据的 html。

Document document = null;
String link = "https://auchan.ua/govjadina-v-kartofel-nom-pjure-so-svekloj-hipp-6440-220-g-297668/";
try {
    document = Jsoup.connect(link).get();
} catch (IOException e) {
    e.printStackTrace();
}
if (document != null) {
    try (FileWriter fileWriter = new FileWriter("output.html")) {
        fileWriter.write(document.toString());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

返回相同。

3.HtmlUnit

    String link = "https://auchan.ua/govjadina-v-kartofel-nom-pjure-so-svekloj-hipp-6440-220-g-297668/";
    WebClient webClient = new WebClient(BrowserVersion.CHROME);
    webClient.getOptions().setJavaScriptEnabled(true);
    webClient.getOptions().setThrowExceptionOnScriptError(false);
    webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
    webClient.setAjaxController(new NicelyResynchronizingAjaxController());
    webClient.waitForBackgroundJavaScriptStartingBefore(5000);

    HtmlPage htmlPage = null;
    try {
        htmlPage = webClient.getPage(link);
        webClient.waitForBackgroundJavaScript(5000);
    } catch (IOException e) {
        e.printStackTrace();
    }
    if (htmlPage!=null){
        try (FileWriter fileWriter = new FileWriter("output.html")) {
            fileWriter.write(Jsoup.parse(htmlPage.asXml()).toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

返回多一点,包括一些 javascripts 标签,但仍然没有任何用处。此外,上面的代码抛出了很多异常,它们甚至不适合控制台。

我也尝试过这样设置代理:

java.net.URLConnection conn = url.openConnection();
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2");

还有这个:

System.setProperty("http.agent", "")

【问题讨论】:

    标签: java web-scraping jsoup nsurlconnection htmlunit


    【解决方案1】:

    您需要使用 Chrome 的开发工具来查看 HTTP 请求/响应

    页面加载了大量的 javascript。这反过来会产生大量的 HTTP 请求并等待响应:第一个看起来很有趣的是:

    https://auchan.ua/graphql 这是一个带有重要 http 标头 referer: https://auchan.ua/govjadina-v-kartofel-nom-pjure-so-svekloj-hipp-6440-220-g-297668/ 的 POST 请求 - 请求的响应正文是:{"data":{"urlResolver":{"type":"PRODUCT","id":297668}}}

    获取产品 ID 值并在后续响应中搜索它,我发现包含产品 ID。响应都是转义的 unicode 字符,但如果您在浏览器中打开 URL,则会呈现内容。

    这个以auchan.ua/graphql/?query=query%20getProductDetail... 开头的特定URL 看起来很有希望,而且special_price 确实与页面上显示的内容相匹配。因此,您需要找到一种从初始页面源中生成/提取这些 URL 的方法。

    link to product details

    您可能还会发现我提供的this response 对处理 JSON 数据很有用。

    您链接到的第二家商店需要用户名/密码,但获取数据的过程可能非常相似;使用开发工具查看 http 请求,找出价格信息的来源(在其中一个响应中查找值),然后尝试从初始 URL 重新创建相同的请求并返回响应。

    祝你好运!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-16
      • 2020-01-01
      • 1970-01-01
      • 2021-12-05
      • 1970-01-01
      • 1970-01-01
      • 2016-03-22
      相关资源
      最近更新 更多