2014-08-27 144 views
2

这是交易。在我的Android应用程序中,我正在使用Jsoup进行一些网页拼写。现在它工作正常,但它太慢了。我在我的代码中做的是:Android HTML Jsoup解析速度

  1. 在Jsoup中通过POST方法登录到页面;
  2. 获取cookies;
  3. 通过重复使用cookie,我正在浏览6页(POST和GET)并且抓取它们(主要是表格和大量的行,我的意思是LOTS ...所以,真的很多foreach循环);
  4. 将所有需要的数据写入SQLiteDatabase;

现在的问题是,它在吸收速度。我的意思是,在按下登录按钮之后,应用程序的登录屏幕中,用户必须在3G中等待10秒,并在WiFi中等待8-10秒(取决于WiFi速度)。当他试图检查数据更新时,它会执行相同的算法+比较SQLiteDatabase表数据。

那么,有没有其他的方法来做这个HTML解析 - 刮在android的东西,使其更快?附:我不能伤心地访问数据库。

编辑:

既然你问我刮的内容,这里是你可以不登录访问几页的一个例子(它是不是真的比别人大表): https://medeine.vgtu.lt/programos/programa.jsp?sid=F&fak=5&prog=87&rus=U&klb=en。现在

,对于代码...我真的不能给你全部的代码,但这里是我应得的表格的每个单元的例子:

document = Jsoup.connect(getContext().getString(R.string.url)) 
        .cookie("JSESSIONID", cookie) 
        .get(); 

      Element table = document.select("table.duomenys").first(); 
      if (table != null) { 
       databaseHandler.openDatabase(); 
       databaseHandler.getDatabase().beginTransaction(); 
       try { 
        for (Element row : table.select("tr.n, tr.l") { 
         Elements columns = row.select("td"); 
         addItem(columns, DatabaseHandler.getTableName()); 
        } 
        databaseHandler.getDatabase().setTransactionSuccessful(); 
       } finally { 
        databaseHandler.getDatabase().endTransaction(); 
       } 
       databaseHandler.closeDatabase(); 
      } 

这里是的addItem( )方法示例:

private void addItem(Elements columns, String tableName) { 
    databaseHandler.addItem(new Item(
      columns.get(0).text(), 
      columns.get(1).text(), 
      columns.get(3).text(), 
      columns.get(4).text() 
    ), tableName); 
} 

而这只是一个页面。其中有6个,其中很少有很多。当然,这是在AsyncTaskLoader的loadInBackground()方法内完成的。

编辑2:

Connection.Response response = Jsoup.connect("https://medeine.vgtu.lt/studentams/submit.jsp") 
       .data("studKnNr", id, "asmKodas", password) 
       .timeout(3000) 
       .method(Connection.Method.POST) 
       .execute(); 

     String cookie = response.cookie("JSESSIONID"); 

     Document document = Jsoup.connect(modules_url) 
       .cookie(cookie_id, cookie) 
       .get(); 

当我想想......可能是因为未解析速度很慢,但登录,并通过6页重定向并在这种情况下,我可以做什么?现在我注意到通过Connection.Response中的.execute()向服务器发送POST并获取cookie需要约2.5秒。

+0

'写入所有需要的数据,以SQLiteDatabase''我没有访问database'选择的答案???? – greenapps 2014-08-27 22:12:37

+1

我正在将下载的数据写入我自己的SQLiteDatabase。由于无法访问我的意思是我无法访问该网站的数据库,所以我必须抓取网站。 很清楚,我在刮大学信息系统网站,但他们还没有授予他们数据库的访问权限。 – env 2014-08-27 22:24:40

+0

如果你的代码要慢,那么你应该在这里发布你的代码,并在互联网上放置一个页面,所以我们不必登录,但可以做一些测试。 – greenapps 2014-08-27 23:22:09

回答

5

因为你的问题是模糊的,你没有提供代码,无论你解析海外省的一些样品,我会提供一个笼统的回答。

  • 优化jsoup查询。由于存在大量数据(大DOM),请尝试 以尽可能高效地解析它们。
  • 最小化循环。在处理数据期间,你确定没有做任何不必要的循环: ?
  • 如果有机会连接大块字符串,请尝试使用 StringBuilder而不是String
  • 尝试使用多个线程。

更新

您可以收到服务器的响应,操纵消息的主体,然后用Jsoup的解析,从而可以最大限度地减少解析的时间。

try { 
    Connection.Response response = Jsoup.connect("ENTER_URL") 
            .userAgent("Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0") 
            .referrer("http://www.google.com") 
            .method(Method.GET) //or Method.POST 
            .execute(); 

    String body = response.body(); 

    String table = body; //Manipulate the string, remove all the data you don't want. 

    Document doc = Jsoup.parse(table); 

    System.out.println(doc); 

} catch(Exception e) { 
    e.printStackTrace(); 
} 

更新2

Connection.Response line takes 2.6 seconds:这个也没有办法。你必须忍受这一点,因为它是延迟服务于你的请求的服务器。毕竟你只拿一次饼干,然后重复使用它们。

但是这部分getting the page可以进行一定的优化。如果你使用我发布的代码,你仍然会有再次发起http请求的开销(这是无法避免的,这是服务器延迟和cookie一样),但是你只会解析你需要的部分,而不是整个回应。这会给你一些改进,但我不相信它会有很大的改进。也许这不值得。但是,您可以尝试仅更改此部分,并告诉我是否有任何改进。如果你真的需要速度的话,你将不得不使用某种形式的并发(多线程)。 这样的事情会产生真正的影响:

  1. 在父线程中检索cookie(仅在开始时)。
  2. 对于每个页面都会创建一个新线程并将Cookie和URL作为参数传递给 。
  3. 每个线程都会分析分配给它的页面。
  4. 所有数据都收集在父线程中。

Check this你如何让你的HTTP请求的并发

+0

为了解析DOM的效率:有没有什么办法可以解析表?因为Jsoup.connect()。get()解析整个HTML页面,并且刚开始抓取它。我只需要桌子。 – env 2014-08-29 10:11:07

+0

检查我的更新 – alkis 2014-08-29 14:10:02

+0

是的,但你看到当我登录时,我必须马上重定向到另一个页面,并且我通过发送GET方法来完成,所以仍然使用.get()。检查编辑2我的登录代码。我认为这个.body()代码只适用于我的情况下的非登录页面。 – env 2014-08-29 15:07:00