Render JavaScript и HTML в (любой) Java-программе (доступное дерево DOM)?

Я знаю, что такого вопроса, наверное, задавали здесь раньше, но, выполнив поиск, я не нашел решения:

Мой вопрос: каковы лучшие библиотеки Java для "полной загрузки любой страницы и рендеринга встроенных JavaScript (-ов), а затем программным образом получить доступ к предоставленной веб-странице (это DOM-Tree!)) и получить DOM Tree как" HTML-источник".

(Что-то похожее на то, что делает firebug в конце, оно отображает страницу, и я получаю доступ к полностью отображенному дереву DOM, поскольку страница выглядит как в браузере! В отличие от этого, если я нажму "показать источник", я получаю только Исходный код JavaScript. Это не то, что я хочу. Мне нужно иметь доступ к отображаемой странице...)

(С рендерингом я имею в виду только рендеринг дерева DOM не визуального рендеринга...)

Это не должна быть одна библиотека, это нормально, чтобы иметь несколько библиотек, которые могут выполнить это вместе (один будет загружен, один рендер...), но из-за динамического характера JavaScript, скорее всего, библиотека JavaScript также будет должны иметь какой-то загрузчик, чтобы полностью отобразить любой асинхронный JS...

Фон: В "старые добрые времена" HttpClient (Apache Library) было всем необходимым для создания собственного очень простого искателя. (Много краулеров, таких как Nutch или Heretrix, все еще строятся вокруг этого основного принципа, главным образом сосредоточившись на стандартном разборе HTML, поэтому я не могу учиться у них) Моя проблема заключается в том, что мне нужно сканировать некоторые веб-сайты, которые в значительной степени зависят от JavaScript и что я не могу разобрать с HttpClient, поскольку мне нужно выполнить JavaScripts раньше...

Большое спасибо! Тим

Ответы

Ответ 1

Это немного вне поля, но если вы планируете запустить свой код на сервере, где у вас есть полный контроль над вашей средой, он может работать...

Установите Firefox (или XulRunner, если вы хотите, чтобы все было в порядке) на вашем компьютере.

Используя систему плагинов Firefox, напишите небольшой плагин, который загружает заданный URL-адрес, ждет несколько секунд, копирует страницу DOM в строку.

из этого плагина, используйте Java LiveConnect API (см. http://jdk6.java.net/plugin2/liveconnect/ и https://developer.mozilla.org/en/LiveConnect), чтобы переместить эту строку в общедоступную статическую функцию в некоторый встроенный код Java, который может либо выполнить необходимую обработку, либо обработать ее до более сложного кода.

Преимущества: вы используете браузер, на который нацелено большинство разработчиков приложений, поэтому наблюдаемое поведение должно быть сопоставимым. Вы также можете обновить браузер по нормальному пути обновления, поэтому ваша библиотека не станет устаревшей по мере изменения стандартов HTML.

Недостатки: вам нужно будет иметь разрешение на запуск приложения без гарнитуры на вашем сервере. У вас также будет сложность взаимодействия между процессами, чтобы беспокоиться.

Я использовал API плагина для вызова Java раньше, и это вполне достижимо. Если вам нужен пример кода, вы должны взглянуть на плагин XQuery - он загружает код XQuery из DOM, передает его в библиотеку Java Saxon для обработки, а затем возвращает результат обратно в браузер. Здесь есть некоторые подробности:

https://developer.mozilla.org/en/XQuery

Ответ 2

Вы можете использовать JavaFX 2 WebEngine. Скачайте JavaFX SDK (возможно, у вас уже есть это, если вы установили JDK7u2 или новее) и попробуйте код ниже.

Он будет печатать html с обработанным javascript. Вы можете раскомментировать линии в середине, чтобы увидеть рендеринг.

public class WebLauncher extends Application {

    @Override
    public void start(Stage stage) {
        final WebView webView = new WebView();
        final WebEngine webEngine = webView.getEngine();
        webEngine.load("http://stackoverflow.com");
        //stage.setScene(new Scene(webView));
        //stage.show();

        webEngine.getLoadWorker().workDoneProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                if (newValue.intValue() == 100 /*percents*/) {
                    try {
                        org.w3c.dom.Document doc = webEngine.getDocument();
                        new XMLSerializer(System.out, new OutputFormat(doc, "UTF-8", true)).serialize(doc);
                    } catch (IOException ex) { 
                        ex.printStackTrace();
                    }
                }
            }
        });

    }

    public static void main(String[] args) {
        launch();
    }

}

Ответ 3

Библиотека Selenium обычно используется для тестирования, но дает вам дистанционное управление большинством стандартных браузеров (IE, Firefox и т.д.), а также безгорный режим без браузера (с использованием HtmlUnit). Поскольку он предназначен для проверки пользовательского интерфейса путем очистки страницы, он может хорошо служить вашим целям.

По моему опыту, он иногда может работать с очень медленным JavaScript, но с осторожным использованием команд "wait" вы можете получить довольно надежные результаты.

У него также есть преимущество, что вы можете управлять страницей, а не просто очищать ее. Это означает, что если вы выполняете некоторые действия на странице, прежде чем перейти к нужным вам данным (нажмите кнопку поиска, нажмите "Далее", теперь очистите), затем вы можете закодировать это в процессе.

Я не знаю, сможете ли вы получить полную DOM в судоходной форме из Selenium, но она обеспечивает получение XPath для различных частей страницы, что вам обычно нужно для соскабливание.

Ответ 4

Вы можете использовать Java, Groovy с или без Grails. Затем используйте Webdriver, Selenium, Spock и Geb для тестирования, но библиотеки полезны для вашего случая. Вы можете реализовать сканер, который не откроет новое окно, а просто время выполнения этих обоих браузеров.

Ответ 7

Я не пробовал этот проект, но я видел несколько реализаций для node.js, которые включают манипуляции с javascript dom.

https://github.com/tmpvar/jsdom