这是交易 . 在我的Android应用程序中,我正在使用Jsoup进行一些网络抓取 . 现在它工作正常,但它太慢了 . 我在我的代码中做的是:
-
通过Jsoup中的POST方法登录页面;
-
获取cookie;
-
通过重用cookie,我将浏览6页(POST和GET)并抓取它们(主要是表格和大量行 . 我的意思是很多......所以,真的很多foreach循环);
-
将所有必需的数据写入SQLiteDatabase;
现在的问题是它的速度很快 . 我的意思是,在按下登录按钮后,在应用程序的登录界面中,用户必须在3G中等待10秒,在WiFi中等待8-10秒(取决于WiFi速度) . 当他试图检查数据更新时,它会使用相同的算法来比较SQLiteDatabase表数据 .
那么,有没有其他方法来做这个HTML解析 - 在android中刮掉东西以使其更快?附:我遗憾地无法访问数据库 .
EDIT:
由于您询问了我正在抓取的内容,以下是您可以在不登录的情况下访问的几个页面的一个示例(与其他人相比,它实际上不是一个大表):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()方法中完成的 .
EDIT 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秒 .
1 回答
由于你的问题含糊不清,你没有提供你的代码,也没有你要解析的DOM的一些样本,我将提供一般答案 .
优化您的jsoup查询 . 由于存在大量数据(大型DOM),请尝试尽可能高效地解析它们 .
最小化循环 . 您确定在处理数据期间没有做任何不必要的循环吗?
如果您连接大块字符串,请尝试使用
StringBuilder
而不是String
.尝试使用多个线程 .
Update
您可以接收服务器的响应,操纵消息正文,然后使用Jsoup的解析,这样您就可以最小化解析的时间 .
Update 2
Connection.Response line takes 2.6 seconds
:这无济于事 . 你必须忍受这个,因为服务器延迟服务你的请求 . 毕竟你只使用一次cookie然后重复使用它们 .但是,这部分
getting the page
可以在某种程度上进行优化 . 如果你使用我发布的代码,你仍然会有再次发出http请求的开销(这是无法避免的,它会相信它会很多 . 也许它甚至不值得 . 但你可以尝试改变这部分只是,告诉我你是否看到任何进步 .此外,如果你真的需要速度,你将不得不使用某种形式的并发(多线程) . 像这样的东西会产生真正的不同:
在父线程中检索cookie(开头只有一次) .
为每个页面创建一个新线程并将cookie和url作为参数传递 .
每个线程都会解析分配给它的页面 .
所有数据都在父线程中收集 .
Check this选择了如何使您的http请求并发的答案