2011-04-05 140 views
19

我有一个基于GWT的页面,我想使用HtmlUnit为它创建一个HTML快照。 使用产品上的Ajax/JavaScript信息加载页面,因此大约1秒钟会出现加载...消息,然后显示内容。HTMLUnit不会等待Javascript

问题是,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()); 

任何想法......?

回答

18

感谢您回复。 我实际上应该早点报告,我已经找到了解决方案。 与FF显然初始化时,Web客户端:

WebClient webClient = new WebClient(BrowserVersion.FIREFOX_3_6); 

它似乎工作。 当使用默认构造函数初始化WebClient时,它默认使用IE7,我猜FF对Ajax有更好的支持,并且是推荐使用的模拟器。

+1

我要评论这一个。有同样的问题,并试图调试整个代码..非常感谢这一点。 – 2012-04-04 20:02:36

+0

嗨。我有同样的问题,使用FIREFOX尽管IE使得页面现在几乎正常加载,但仍然卡住...正在加载...消息,它应该是大约9秒,用你的部分代码以及没有:(请帮助 – silvestrairwave 2014-04-04 09:41:56

+0

谢谢!我已经失去了几个小时的调试,直到我发现你的意见! – kotslon 2016-02-04 07:44:33

14

我相信在默认情况下,NicelyResynchronizingAjaxController只会重新同步由用户操作导致的AJAX调用,方法是跟踪源自哪个线程。也许GWT生成的JavaScript正在被NicelyResynchronizingAjaxController不想等的其他线程调用。

尝试宣告自己AjaxController无论起始线程的一切同步:

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

迄今为止提供的解决方案都不适用于我。我结束了Dan Alvizu's solution +我自己砍:“请稍等”

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(如果使用的话)。当然,如果你有冒险精神,你可以简单地提供足够的毫秒数。

4

作为文档状态,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...") 
+1

这样的投票对我来说工作到现在为止以及。 – MrSmith42 2014-12-23 12:55:04