Android HTML Jsoup解析速度

emi*_*ius 3 performance android web-scraping jsoup

这是交易.在我的Android应用程序中,我正在使用Jsoup进行一些网络抓取.现在它工作正常,但它太慢了.我在我的代码中做的是:

  1. 在Jsoup中通过POST方法登录页面;
  2. 获取cookie;
  3. 通过重用cookie我将经历6个页面(POST和GET)并抓取它们(主要是表格和许多行.我的意思是很多......所以,真的很多foreach循环);
  4. 将所有必需的数据写入SQLiteDatabase;

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

那么,有没有其他方法来做这个HTML解析 - 在android中刮掉东西以使其更快?PS我遗憾地无法访问数据库.

编辑:

既然你问过我正在抓取的内容,这里是你可以在不登录的情况下访问的几个页面的一个例子(与其他人相比,这不是一个很大的表):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();
            }
Run Code Online (Sandbox Code Playgroud)

这是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);
}
Run Code Online (Sandbox Code Playgroud)

它只是一页.其中有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();
Run Code Online (Sandbox Code Playgroud)

当我想到它时...可能不是解析速度慢,而是登录并重定向到6页,在这种情况下我什么都不做?现在我注意到在Connection.Response中通过.execute()发送POST到服务器并且获取cookie需要大约2.5秒.

Alk*_*ris 5

由于您的问题含糊不清,并且您没有提供代码,也没有提供正在解析的DOM的一些示例,我将提供一般答案.

  • 优化您的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();
}
Run Code Online (Sandbox Code Playgroud)

更新2

Connection.Response line takes 2.6 seconds:这无济于事.你必须忍受这个,因为服务器延迟服务你的请求.毕竟你只使用一次cookie然后重复使用它们.

但是,这部分getting the page可以在某种程度上进行优化.如果您使用我贴的代码,您仍然可以再次使HTTP请求的开销(这是无法避免的,它的服务器延迟与饼干),但你只会解析您需要的部分,而不是整个回应.这会给你一些改进,但我不相信它会有多大改进.也许它甚至不值得.但您可以尝试仅更改此部分,并告诉我您是否看到任何改进.

Document document = Jsoup.connect(modules_url)
                .cookie(cookie_id, cookie)
                .get();
Run Code Online (Sandbox Code Playgroud)

此外,如果你真的需要速度,你将不得不使用某种形式的并发(多线程).这样的事情会产生真正的不同:

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

检查此选定答案,了解如何使http请求同时进行