Как собрать цену с динамически обновляемых веб-страниц?

У меня проблема, когда я пытаюсь получить цену с динамически обновляемых веб-страниц. Я имею в виду, что львиная доля html-кода не получена такими способами, как UrlConnection, Jsoup, HtmlUnit. Я не особо разбираюсь в веб-скрапинге, но думаю, проблема в том, что интернет-магазины вроде этих: Ашан, Сильпо использует javascript и ajax для загрузки основной информации о товарах. И, на мой взгляд, проблема в редиректе или делеи, которые не позволяют получить полностью загруженный html файл со всеми необходимыми данными. Итак, вопрос в том, как вычистить цену из ссылок выше?

Я уже пробовал несколько подходов:

  1. URLConnection

        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 без данных о ценах.

  2. Суп

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", "")

person Danil Andriychenko    schedule 12.08.2020    source источник


Ответы (1)


Вам нужно использовать инструменты Chrome Dev для просмотра HTTP-запросов/ответов.

Страница загружает тонны javascript. Это, в свою очередь, производит целую кучу HTTP-запросов и ждет ответов: первое, что выглядит интересным, это:

https://auchan.ua/graphql, который представляет собой POST-запрос с важным http-заголовком referer: https://auchan.ua/govjadina-v-kartofel-nom-pjure-so-svekloj-hipp-6440-220-g-297668/ — тело ответа для запроса: {"data":{"urlResolver":{"type":"PRODUCT","id":297668}}}

Взяв значение идентификатора продукта и найдя его в последующих ответах, я обнаружил, что идентификатор продукта содержится. Все ответы представляют собой экранированные символы Юникода, но если вы откроете URL-адреса в браузере, содержимое будет отображаться.

Этот конкретный URL-адрес, начинающийся с auchan.ua/graphql/?query=query%20getProductDetail..., выглядел многообещающе, и, конечно же, special_price соответствует тому, что отображается на странице. Поэтому вам нужно найти способ создания/извлечения этих URL-адресов из исходного источника страницы.

Вы также можете найти этот ответ, который я дал полезно для обработки данных JSON.

Второй магазин, на который вы ссылаетесь, требует имя пользователя/пароль, но процесс получения данных, скорее всего, будет очень похожим; используйте инструменты разработчика для просмотра http-запросов, выясните, откуда поступает информация о цене (найдите значение в одном из ответов), затем попробуйте воссоздать тот же запрос из исходного URL-адреса и возвращенного ответа.

Удачи!

ссылка на сведения о продукте

person Rob Evans    schedule 13.08.2020