Android利用Jsoup抓取数据,再也不怕写App没有数据啦
因为最近有部分小伙伴私信我询问关于我很久前写的一个教务系统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.jianshu.com/ ,我们通过浏览器访问它,并按F12(这里我使用的chrome浏览器)。
简书首页 get请求这里可以看到简书首页的html代码,我们要实现的就是把首页的文章列表提取出来。
目标明确,可以开始撸代码了。
首先先在build.gradle里添加Jsoup的依赖
dependencies {
compile 'org.jsoup:jsoup:1.10.2'
}
既然Jsoup是对html进行操作,那么首先我们肯定要拿到html嘛,这里我使用okhttp发起请求,大家也可以根据自己喜好自行替换
Request request = new Request.Builder().
url("http://www.jianshu.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图片
Demo总结
Ok啦,通过Jsoup可以抓取各种网页的数据,例如你学校的教务网等等,这里我们只是简单介绍了一下Jsoup的基本用法,细心的童鞋肯定发现啦,使用Jsoup抓取数据时如果抓取的网站的html发生改变,那么代码也得随之改变,这也是其缺点之一吧。那么本文就到此啦,如有哪里讲解有误还望体谅~ 谢谢大家~