Jsoup抓取网页数据完成一个简易的Android新闻APP
2017-01-22 20:56
387 查看
前言:作为一个篮球迷,每天必刷NBA新闻。用了那么多新闻APP,就想自己能不能也做个简易的新闻APP。于是便使用Jsoup抓取了虎扑NBA新闻的数据,完成了一个简易的新闻APP。虽然没什么技术含量,但还是写一下过程,满足一下菜鸟小小的成就感。
Jsoup的中文文档:点击这里
Jsoup的jar包下载地址:点击这里
我们所要做的便是获取图中每条新闻的新闻标题、新闻概要、新闻时间与来源以及新闻的链接地址这四个信息,而后用一个实体类News封装上述四个数据,再布局到ListView上。点击ListView的每个子项,便将该子项所显示的新闻的链接地址用一个WebView显示出来,便大功告成。效果如图:
2.修改activity_main.xml的布局,简单加入一个ListView,并设置一下Listview的每两个子项间的间隔的距离和颜色
3.建立一个实体类News来封装我们等会要从网页中获取的新闻的标题、概要、时间与来源、链接地址这四个数据。很简单,用四个变量分别代表上述四个数据,并建立相应的构造方法以及四个变量的get与set方法。
4.最重要的一步:利用Jsoup获取虎扑NBA新闻网页的数据,并封装到News实体类中。就简单概述下实现方法
查看虎扑NBA新闻的网页源代码。谷歌浏览器,右键-查看网页源代码。其他浏览器应该都差不多。
我们直接查看显示新闻列表的这部分代码,我们截图下两条新闻的代码来进行分析
新闻1源代码:
新闻2源代码:
分析上图两条新闻的源代码,找到我们所打算要获取的新闻的标题、概要、时间与来源、链接地址这四个数据。我们可以发现在每条新闻的[div class=”list-hd”][/div]这个标签下,存在新闻的链接地址与新闻的标题这两个数据。而我们所要做的便是利用Jsoup将这两个数据解析出来:
首先用Jsoup.connect(“所要抓取数据的网址”).get()获取到一个Document对象
用doc.select(“div.list-hd”)这个方法,返回一个Elements对象,封装了每条新闻[div class=”list-hd”][/div]标签中的内容,数据格式为:[{新闻1},{新闻2},{新闻3},{新闻4}……]
用for循环遍历titleLinks,对于每个Element对象:
用e.select(“a”).text()便获取到[a][/a]间的内容,即新闻标题;
用e.select(“a”).attr(“href”)便获取到每个标签中的href的值,即新闻的链接地址
同理对于另外两个数据:新闻简介和新闻时间及来源,我们分析源代码并进行解析
新闻简介源代码
用如下代码获得新闻简介
新闻时间及来源源代码
用如下代码获得新闻时间与来源
综上,我们就获取到了我们所需要的数据了,为此我们在MainActivity中声明一个getNews()方法,在方法中,我们开启一个线程来进行数据的获取。完整代码如下:
上一段代码相信通过备注就可以理解了,通过解析虎扑NBA新闻20页的每一页的网址,获取到每条新闻所需的数据,封装到实体类News中,再加入到MainActivity中声明的泛型为News的List即newsList中。等全部20页数据都获取到之后,用Message.what=1来作为数据加载完成的标志,并用Handler.sendMessage()将子线程的消息发送到主线程,通知主线程数据已加载完成,可以将数据加载到ListView上显示出来。
5.剩下的就简单了 ,为ListView做相关的配置
news_item.xml:为ListView的item指定布局。放置三个TextView用来显示新闻标题,新闻概要,新闻时间及来源;
NewsAdapter.java:为ListView加载数据
6.建立NewsDisplayActivity用于显示新闻的具体内容。
布局activity_display_news.xml:简单放入一个WebView,用于显示新闻
NewsDisplayActivity.java
7.MainActivity用getNews()获取到数据后,在handlerMessage()方法里接受到子线程获取完数据的消息后,开始为ListView加载数据。并为ListView的item设置点击事件,当点击item时,将该item所对应的新闻的网址传递给NewsDisplayActivity,NewsDisplayActivity得到网址后用WebView加载该网址,便可看到新闻
源码下载地址:点击这里
总结:虽然只是一个简单的应用,但还是有所收获。菜鸟的点滴积累,希望能早日有所成长
关于Jsoup
jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。Jsoup的中文文档:点击这里
Jsoup的jar包下载地址:点击这里
分析与思路
虎扑NBA新闻网页的新闻列表如图所示:我们所要做的便是获取图中每条新闻的新闻标题、新闻概要、新闻时间与来源以及新闻的链接地址这四个信息,而后用一个实体类News封装上述四个数据,再布局到ListView上。点击ListView的每个子项,便将该子项所显示的新闻的链接地址用一个WebView显示出来,便大功告成。效果如图:
具体实现过程
1.在AndroidStudio新建工程JsoupTest,而后将Jsoup的jar包【下载地址】拷到项目的libs下,然后右键Add As Library…2.修改activity_main.xml的布局,简单加入一个ListView,并设置一下Listview的每两个子项间的间隔的距离和颜色
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/news_lv" android:dividerHeight="7dp" android:divider="#dcdcdc"> </ListView> </LinearLayout>
3.建立一个实体类News来封装我们等会要从网页中获取的新闻的标题、概要、时间与来源、链接地址这四个数据。很简单,用四个变量分别代表上述四个数据,并建立相应的构造方法以及四个变量的get与set方法。
public class News { private String newsTitle; //新闻标题 private String newsUrl; //新闻链接地址 private String desc; //新闻概要 private String newsTime; //新闻时间与来源 public News(String newsTitle, String newsUrl, String desc, String newsTime) { this.newsTitle = newsTitle; this.newsUrl = newsUrl; this.desc = desc; this.newsTime = newsTime; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public String getNewsTime() { return newsTime; } public void setNewsTime(String newsTime) { this.newsTime = newsTime; } public String getNewsTitle() { return newsTitle; } public void setNewsTitle(String newsTitle) { this.newsTitle = newsTitle; } public String getNewsUrl() { return newsUrl; } public void setNewsUrl(String newsUrl) { this.newsUrl = newsUrl; } }
4.最重要的一步:利用Jsoup获取虎扑NBA新闻网页的数据,并封装到News实体类中。就简单概述下实现方法
查看虎扑NBA新闻的网页源代码。谷歌浏览器,右键-查看网页源代码。其他浏览器应该都差不多。
我们直接查看显示新闻列表的这部分代码,我们截图下两条新闻的代码来进行分析
新闻1源代码:
新闻2源代码:
分析上图两条新闻的源代码,找到我们所打算要获取的新闻的标题、概要、时间与来源、链接地址这四个数据。我们可以发现在每条新闻的[div class=”list-hd”][/div]这个标签下,存在新闻的链接地址与新闻的标题这两个数据。而我们所要做的便是利用Jsoup将这两个数据解析出来:
首先用Jsoup.connect(“所要抓取数据的网址”).get()获取到一个Document对象
Document doc = Jsoup.connect("https://voice.hupu.com/nba/").get();
用doc.select(“div.list-hd”)这个方法,返回一个Elements对象,封装了每条新闻[div class=”list-hd”][/div]标签中的内容,数据格式为:[{新闻1},{新闻2},{新闻3},{新闻4}……]
用for循环遍历titleLinks,对于每个Element对象:
用e.select(“a”).text()便获取到[a][/a]间的内容,即新闻标题;
用e.select(“a”).attr(“href”)便获取到每个标签中的href的值,即新闻的链接地址
Elements titleLinks = doc.select("div.list-hd"); for(Element e:titleLinks){ String title = e.select("a").text(); String uri = e.select("a").attr("href"); }
同理对于另外两个数据:新闻简介和新闻时间及来源,我们分析源代码并进行解析
新闻简介源代码
用如下代码获得新闻简介
Elements descLinks = doc.select("div.list-content"); for(Element e:titleLinks){ String desc = e.select("span").text(); }
新闻时间及来源源代码
用如下代码获得新闻时间与来源
Elements timeLinks = doc.select("div.otherInfo"); for(Element e:timeLinks){ String time = e.select("span.other-left").select("a").text(); }
综上,我们就获取到了我们所需要的数据了,为此我们在MainActivity中声明一个getNews()方法,在方法中,我们开启一个线程来进行数据的获取。完整代码如下:
private void getNews(){ new Thread(new Runnable() { @Override public void run() { try{ //获取虎扑新闻20页的数据,网址格式为:https://voice.hupu.com/nba/第几页 for(int i = 1;i<=20;i++) { Document doc = Jsoup.connect("https://voice.hupu.com/nba/" + Integer.toString(i)).get(); Elements titleLinks = doc.select("div.list-hd"); //解析来获取每条新闻的标题与链接地址 Elements descLinks = doc.select("div.list-content");//解析来获取每条新闻的简介 Elements timeLinks = doc.select("div.otherInfo"); //解析来获取每条新闻的时间与来源 //for循环遍历获取到每条新闻的四个数据并封装到News实体类中 for(int j = 0;j < titleLinks.size();j++){ String title = titleLinks.get(j).select("a").text(); String uri = titleLinks.get(j).select("a").attr("href"); String desc = descLinks.get(j).select("span").text(); String time = timeLinks.get(j).select("span.other-left").select("a").text(); News news = new News(title,uri,desc,time); newsList.add(news); } } Message msg = new Message(); msg.what = 1; handler.sendMessage(msg); }catch (Exception e){ e.printStackTrace(); } } }).start(); }
上一段代码相信通过备注就可以理解了,通过解析虎扑NBA新闻20页的每一页的网址,获取到每条新闻所需的数据,封装到实体类News中,再加入到MainActivity中声明的泛型为News的List即newsList中。等全部20页数据都获取到之后,用Message.what=1来作为数据加载完成的标志,并用Handler.sendMessage()将子线程的消息发送到主线程,通知主线程数据已加载完成,可以将数据加载到ListView上显示出来。
5.剩下的就简单了 ,为ListView做相关的配置
news_item.xml:为ListView的item指定布局。放置三个TextView用来显示新闻标题,新闻概要,新闻时间及来源;
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:orientation="vertical" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginTop="10dp" android:layout_marginRight="5dp" android:layout_marginBottom="5dp" android:id="@+id/news_title" android:gravity="center_horizontal" android:textColor="#000" android:textSize="18sp"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="12sp" android:id="@+id/news_desc" android:layout_marginBottom="6dp" android:layout_marginLeft="10dp" android:gravity="center_horizontal" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/news_time" android:layout_marginBottom="6dp" android:textSize="10sp" android:textColor="#708090" android:gravity="center_horizontal" android:layout_marginRight="30dp" /> </LinearLayout>
NewsAdapter.java:为ListView加载数据
public class NewsAdapter extends BaseAdapter { private List<News> newsList; private View view; private Context mContext; private ViewHolder viewHolder; public NewsAdapter(Context mContext, List<News> newsList) { this.newsList = newsList; this.mContext= mContext; } @Override public int getCount() { return newsList.size(); } @Override public Object getItem(int position) { return newsList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { view = LayoutInflater.from(mContext).inflate(R.layout.news_item, null); viewHolder = new ViewHolder(); viewHolder.newsTitle = (TextView) view .findViewById(R.id.news_title); viewHolder.newsDesc = (TextView)view.findViewById(R.id.news_desc); viewHolder.newsTime = (TextView)view.findViewById(R.id.news_time); view.setTag(viewHolder); } else { view = convertView; viewHolder = (ViewHolder) view.getTag(); } viewHolder.newsTitle.setText(newsList.get(position).getNewsTitle()); viewHolder.newsDesc.setText(newsList.get(position).getDesc()); viewHolder.newsTime.setText("来自 : "+newsList.get(position).getNewsTime()); return view; } class ViewHolder{ TextView newsTitle; TextView newsDesc; TextView newsTime; } }
6.建立NewsDisplayActivity用于显示新闻的具体内容。
布局activity_display_news.xml:简单放入一个WebView,用于显示新闻
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <WebView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/web_view"></WebView> </LinearLayout>
NewsDisplayActivity.java
public class NewsDisplayActvivity extends AppCompatActivity { private String newsUrl; @Override protected void onCreate(Bundle savedInstanceState) { b474 super.onCreate(savedInstanceState); setContentView(R.layout.activity_news_display); newsUrl = getIntent().getStringExtra("news_url"); WebView webView = (WebView) findViewById(R.id.web_view); webView.getSettings().setJavaScriptEnabled(true); webView.setWebViewClient(new WebViewClient()); webView.loadUrl(newsUrl); } }
7.MainActivity用getNews()获取到数据后,在handlerMessage()方法里接受到子线程获取完数据的消息后,开始为ListView加载数据。并为ListView的item设置点击事件,当点击item时,将该item所对应的新闻的网址传递给NewsDisplayActivity,NewsDisplayActivity得到网址后用WebView加载该网址,便可看到新闻
public class MainActivity extends AppCompatActivity { private List<News> newsList; private NewsAdapter adapter; private Handler handler; private ListView lv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); newsList = new ArrayList<>(); lv = (ListView) findViewById(R.id.news_lv); getNews(); handler = new Handler(){ @Override public void handleMessage(Message msg) { if(msg.what == 1){ adapter = new NewsAdapter(MainActivity.this,newsList); lv.setAdapter(adapter); lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { News news = newsList.get(position); Intent intent = new Intent(MainActivity.this,NewsDisplayActvivity.class); intent.putExtra("news_url",news.getNewsUrl()); startActivity(intent); } }); } } }; } private void getNews(){ new Thread(new Runnable() { @Override public void run() { try{ //获取虎扑新闻20页的数据,网址格式为:https://voice.hupu.com/nba/第几页 for(int i = 1;i<=20;i++) { Document doc = Jsoup.connect("https://voice.hupu.com/nba/" + Integer.toString(i)).get(); Elements titleLinks = doc.select("div.list-hd"); //解析来获取每条新闻的标题与链接地址 Elements descLinks = doc.select("div.list-content");//解析来获取每条新闻的简介 Elements timeLinks = doc.select("div.otherInfo"); //解析来获取每条新闻的时间与来源 for(int j = 0;j < titleLinks.size();j++){ String title = titleLinks.get(j).select("a").text(); String uri = titleLinks.get(j).select("a").attr("href"); String desc = descLinks.get(j).select("span").text(); String time = timeLinks.get(j).select("span.other-left").select("a").text(); News news = new News(title,uri,desc,time); newsList.add(news); } } Message msg = new Message(); msg.what = 1; handler.sendMessage(msg); }catch (Exception e){ e.printStackTrace(); } } }).start(); } }
源码下载地址:点击这里
总结:虽然只是一个简单的应用,但还是有所收获。菜鸟的点滴积累,希望能早日有所成长
相关文章推荐
- Jsoup抓取网页数据完成一个简易的Android新闻APP
- Android App使用Jsoup抓取网页数据显示
- android:获取富文本图片和使用Jsoup抓取腾讯新闻网页数据
- Android自由开发者 通过Jsoup抓取网页数据
- Jsoup一个简短的引论——采用Java抓取网页数据
- Android 利用jsoup 抓取腾讯应用市场的软件APP,作为我们自己应用的数据
- jsoup抓取网页上的数据,Android同时获取数据
- 【Android 我的博客APP】1.抓取博客首页文章列表内容——网页数据抓取
- Android中使用jsoup对网页数据的抓取和修改
- Jsoup抓取数据实现为一个网站做第三方Android客户端
- Android 利用jsoup 抓取腾讯应用市场的软件APP,作为我们自己应用的数据
- android一步一步完成一个简易记事本
- 一个简单的使用python抓取网页中的水文数据的程序
- jsoup技术抓取网页数据大全
- Jsoup简介——使用Java抓取网页数据
- 从零开始打造一个新闻订阅APP之Android篇(二、从“逛”页面谈谈多种格式listview的实现细节)
- 一个极其简洁的Python网页抓取程序,自己主动从雅虎財经抓取股票数据
- 一个极其简洁的Python网页抓取程序,自动从雅虎财经抓取股票数据
- 网页信息抓取进阶 支持Js生成数据 Jsoup的不足之处
- (Android+IOS)正在做一个新闻App,做的差不多了,听听大家的建议 (图)