2011-04-05 22 views
19

Tengo una página basada en GWT que me gustaría crear una instantánea HTML para ello utilizando HtmlUnit. La página carga información de Ajax/JavaScript en un producto, por lo que durante aproximadamente 1 segundo hay un mensaje Cargando ... y luego aparece el contenido.HTMLUnit no espera para Javascript

El problema es que HtmlUnit no parece capturar la información y todo lo que obtengo es el tramo "Cargando ...".

A continuación se muestra un código experimental con HtmlUnit en el que intento darle tiempo suficiente para esperar la carga de los datos, pero no parece cambiar nada y aún no puedo capturar los datos cargados por el Javascript de 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()); 

¿Alguna idea ...?

Respuesta

18

Gracias por responder. Debo haber informado esto antes de haber encontrado la solución yo mismo. Al parecer, cuando la inicialización de cliente Web con FF:

WebClient webClient = new WebClient(BrowserVersion.FIREFOX_3_6); 

Se parece estar funcionando. Al inicializar WebClient con el constructor predeterminado, usa IE7 de manera predeterminada y supongo que FF tiene mejor soporte para Ajax y es el emulador recomendado para usar.

+1

Tengo que comentar este. Tenía el mismo problema e intentaba depurar todo el código. Muchas gracias por esto. –

+0

Hola. Tengo el mismo problema, el uso de FIREFOX a pesar de IE hace que las páginas se carguen casi correctamente ahora, pero aún estoy atascado en ... Cargando ...mensaje, debería ser alrededor de 9 segundos, utilizó su parte de código y nada :(por favor ayuda – silvestrairwave

+0

¡Gracias! He perdido varias HORAS en la depuración hasta que encontré su comentario! – kotslon

14

Creo que por defecto NicelyResynchronizingAjaxController solo volverá a sincronizar las llamadas AJAX que fueron causadas por una acción del usuario, mediante el seguimiento de la cadena desde la que se originó. Quizás el JavaScript generado por GWT está siendo llamado por algún otro hilo que NicelyResynchronizingAjaxController no desea esperar.

Try declarar su propia AjaxController para sincronizar con todo, independientemente de hilo originario:

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

Ninguna de las soluciones proporcionadas hasta ahora funcionó para mí. Terminé con Dan Alvizu's solution + mi propio truco: "! Por favor espere mientras se carga"

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

Ni que decir tiene, debe reemplazarse con el texto que se muestre mientras se carga la página. Si no hay texto, tal vez haya una forma de verificar la existencia de algún gif (si se usa). Por supuesto, simplemente podría proporcionar un valor de milisegundos lo suficientemente grande si se siente aventurero.

4

Como estados de documentación, waitForBackgroundJavaScript es experimental:

API experimental: Se puede variar de una liberación y puede que todavía no funcione a la perfección!

El siguiente enfoque siempre ha trabajado para mí, independientemente de la BrowserVersion utilizado:

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

Nota aCondition es lo que usted está comprobando. EG:

page.getElementById("loading-text-element").asText().equals("Loading...") 
+1

Las encuestas como esta funcionaron bien para mí hasta ahora también. – MrSmith42