2014-08-27 185 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