因為最近有部分小伙伴私信我詢問關于我很久前寫的一個教務系統App的一些問題,鑒于那個項目實在是停止維護太久了,代碼都是一年多前寫的,已經登陸不進去了,本著授人與魚不如授人與漁的原則,于是寫了這篇博客。
原理很簡單,閱讀本文大概需要3分鐘。
Jsoup介紹
先附上官方介紹:
Jsoup is a Java library for working with real-world HTML. It provides a very convenient API for extracting and manipulating data, using the best of DOM, CSS, and jquery-like methods.
Jsoup是一個用來處理html文本的java庫。它提供了非常方便的API,可以通過dom,css或者類似jquery的方法來提取和操作數據。
嗯,所以他到底是干嘛的呢? 當我們訪問一個網站拿到它的html代碼的時候,往往我們所需要的一些數據就已經包含在html里,Jsoup就是幫我們把這些我們想要的數據提取出來。還是不夠清晰明了?沒關系,我們一起來看一個demo。
Demo
這里我們以簡書為例子,抓取簡書中我們想要的數據。
眾所周知,簡書的url為http://www.lxweimin.com/ ,我們通過瀏覽器訪問它,并按F12(這里我使用的chrome瀏覽器)。
這里可以看到簡書首頁的html代碼,我們要實現的就是把首頁的文章列表提取出來。
目標明確,可以開始擼代碼了。
首先先在build.gradle里添加Jsoup的依賴
dependencies {
compile 'org.jsoup:jsoup:1.10.2'
}
既然Jsoup是對html進行操作,那么首先我們肯定要拿到html嘛,這里我使用okhttp發起請求,大家也可以根據自己喜好自行替換
Request request = new Request.Builder().
url("http://www.lxweimin.com").
//如果請求的url需要提交參數,那么需改為post方式并提交對應的參數
get().
build();
okHttpClient.newCall(request).enqueue(this);
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
String result = response.body().string();
parseHtml(result);
}
}
這里沒什么特別的,無非就是發送請求,拿到返回的html。
好現在我們已經成功拿到簡書首頁的html代碼,這里我們先回到瀏覽器,按住ctrl+shift+c(chrome瀏覽器下的快捷鍵) ,點擊一下列表的其中一篇文章,
可以看到,li這個標簽是包含在id為list-container的div中的ul里面。
點擊標題,可以看到標題是包含在li里面的class為title的a標簽里面的,并且文章的詳情頁面的url也包含在href屬性里面,對jq或者js熟悉的童鞋可能知道,在jq或者js中我們是可以通過標簽來尋找元素的,回顧一下Jsoup的簡介,可以使用類似jquery的方法提取或者操縱數據,是不是大概明白了。
我們來看一下代碼實現
private void parseHtml(String html) {
//將html轉為Document對象
Document document = Jsoup.parse(html);
//獲得li的元素集合
Elements elements = document.select("div#list-container ul li");
List<BlogModel> lists = new ArrayList<>();
BlogModel blogModel;
for (Element element : elements) {
//獲得作者
String author = element.select("div.name a").first().text();
//獲得標題
String title = element.select("a.title").first().text();
//獲得圖片url,因為文章有可能沒有圖片,所以這里需要特殊處理一下
String image = element.select("a.wrap-img").first() != null ?
element.select("a.wrap-img").first().children().first().attr("src") : "";
//獲得文章詳情url
String targetUrl = element.select("a.title").first().attr("href");
blogModel = new BlogModel();
blogModel.setAuthor(author);
blogModel.setName(title);
blogModel.setImage(image);
blogModel.setTargetUrl(targetUrl);
lists.add(blogModel);
}
}
這里我們將拿到的數據都封裝成一個BlogModel
對象,BlogModel
的代碼很簡單
public class BlogModel {
private String author;
private String name;
private String image;
private String targetUrl;
//get和set方法...
}
現在我們已經拿到需要的數據了,接下來無非就是展示了。這里我是用RecyclerView,簡單貼一下Adapter的代碼
static class MyAdapter extends RecyclerView.Adapter<ViewHolder> {
private Context context;
private List<BlogModel> blogModels;
public MyAdapter(Context context) {
this.context = context;
}
public void setBlogModels(List<BlogModel> blogModels) {
this.blogModels = blogModels;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(View.inflate(context, R.layout.item_blog, null));
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.tvTitle.setText(blogModels.get(position).getName());
Glide.with(context).load(blogModels.get(position).getImage()).into(holder.ivImg);
}
@Override
public int getItemCount() {
return blogModels.size();
}
}
怎么去展示數據大家肯定都很熟悉了,這里就不啰嗦了,最后上一下demo圖片
總結
Ok啦,通過Jsoup可以抓取各種網頁的數據,例如你學校的教務網等等,這里我們只是簡單介紹了一下Jsoup的基本用法,細心的童鞋肯定發現啦,使用Jsoup抓取數據時如果抓取的網站的html發生改變,那么代碼也得隨之改變,這也是其缺點之一吧。那么本文就到此啦,如有哪里講解有誤還望體諒~ 謝謝大家~