HTMLUnit не ждет Javascript - PullRequest
       47

HTMLUnit не ждет Javascript

20 голосов
/ 05 апреля 2011

У меня есть страница на основе GWT, для которой я хотел бы создать снимок HTML для нее с помощью HtmlUnit. Страница загружается с использованием информации Ajax / JavaScript о продукте, поэтому в течение примерно 1 секунды появляется сообщение «Загрузка ...», а затем отображается содержимое.

Проблема в том, что HtmlUnit, похоже, не собирает информацию, и все, что я получаю, это диапазон "Загрузка ...".

Ниже приведен экспериментальный код с HtmlUnit, где я пытаюсь дать ему достаточно времени, чтобы дождаться загрузки данных, но, похоже, он ничего не меняет, и я все еще не могу захватить данные, загруженные JavaScript GWT.

        WebClient webClient = new WebClient();
        webClient.setJavaScriptEnabled(true);
        webClient.setThrowExceptionOnScriptError(false);
        webClient.setAjaxController(new NicelyResynchronizingAjaxController()); 

        WebRequest request = new WebRequest(new URL("<my_url>"));
        HtmlPage page = webClient.getPage(request);

        int i = webClient.waitForBackgroundJavaScript(1000);

        while (i > 0)
        {
            i = webClient.waitForBackgroundJavaScript(1000);

            if (i == 0)
            {
                break;
            }
            synchronized (page) 
            {
                System.out.println("wait");
                page.wait(500);
            }
        }

        webClient.getAjaxController().processSynchron(page, request, false);

        System.out.println(page.asXml());

Есть идеи ...?

Ответы [ 4 ]

19 голосов
/ 20 апреля 2011

Спасибо, что ответили.Я действительно должен был сообщить об этом раньше, чтобы найти решение сам.Видимо при инициализации WebClient с FF:

WebClient webClient = new WebClient(BrowserVersion.FIREFOX_3_6);

Кажется, он работает.При инициализации WebClient конструктором по умолчанию он использует IE7 по умолчанию, и я думаю, что FF лучше поддерживает Ajax и является рекомендуемым эмулятором для использования.

14 голосов
/ 20 апреля 2011

Я считаю, что по умолчанию NicelyResynchronizingAjaxController будет только ресинхронизировать вызовы AJAX, вызванные действием пользователя, отслеживая, из какого потока он возник.Возможно, сгенерированный GWT JavaScript вызывается каким-то другим потоком, который NicelyResynchronizingAjaxController не хочет ждать.

Попробуйте объявить свой собственный AjaxController для синхронизации со всем независимо от источника потока:

webClient.setAjaxController(new AjaxController(){
    @Override
    public boolean processSynchron(HtmlPage page, WebRequest request, boolean async)
    {
        return true;
    }
});
3 голосов
/ 13 августа 2014

Как указано в документации, waitForBackgroundJavaScript является экспериментальным:

Экспериментальный API: может быть изменен в следующем выпуске и может еще не работать идеально!

Следующий подход всегда работал для меня, независимо от используемого BrowserVersion:

int tries = 5;  // Amount of tries to avoid infinite loop
while (tries > 0 && aCondition) {
    tries--;
    synchronized(page) {
        page.wait(2000);  // How often to check
    }
}

Примечание aCondition - это то, что вы проверяете.EG:

page.getElementById("loading-text-element").asText().equals("Loading...")
2 голосов
/ 06 августа 2014

Ни одно из предоставленных решений не помогло мне. Я получил решение Дана Алвизу + мой собственный взлом:

private WebClient webClient = new WebClient();

public void scrapPage() {
    makeWebClientWaitThroughJavaScriptLoadings();
    HtmlPage page = login();
    //do something that causes JavaScript loading
    waitOutLoading(page);
}

private void makeWebClientWaitThroughJavaScriptLoadings() {
    webClient.setAjaxController(new AjaxController(){
        @Override
        public boolean processSynchron(HtmlPage page, WebRequest request, boolean async)
        {
            return true;
        }
    });
}

private void waitOutLoading(HtmlPage page) {
    while(page.asText().contains("Please wait while loading!")){
        webClient.waitForBackgroundJavaScript(100);
    }
}

Нет необходимости говорить: "Пожалуйста, подождите, пока идет загрузка!" должен быть заменен тем текстом, который отображается во время загрузки вашей страницы. Если текста нет, возможно, есть способ проверить наличие какого-либо gif (если он используется). Конечно, вы можете просто указать достаточно большое значение в миллисекундах, если вы чувствуете себя предприимчивым.

...