Подтвердить что ты не робот

HTMLUnit не ждет Javascript

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

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

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

        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());

Любые идеи...?

4b9b3361

Ответ 1

Спасибо, что ответили. На самом деле я должен был сообщить об этом раньше, что сам нашел решение. По-видимому, при инициализации WebClient с FF:

WebClient webClient = new WebClient(BrowserVersion.FIREFOX_3_6);

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

Ответ 2

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

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

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

Ответ 3

Как указано в документации, 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...")

Ответ 4

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

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 (если он используется). Конечно, вы могли бы просто предоставить достаточно большое миллисекунду значение, если вы чувствуете приключения.