第一篇技术博客,写得不好请见谅,谢谢(^_^)
由于最近师弟师妹们学习Android的需求,于是就写了此篇博客并且与各位分享一下。

整篇博客总共分为两部分。

第一部分搭建一个新闻列表界面(ListView列表)。
第二部分新闻数据的抓取(使用正则表达式)

涉及到的技术,java正则表达式,java网络编程(IO流)。
编译器:android studio

整个Demo项目的结构如下所示。

1. 第一部分,搭建一个新闻列表界面

MainActivity.java文件代码如下

package per.edward.androidnewsreader;import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;import java.util.ArrayList;
import java.util.List;import per.edward.androidnewsreader.adapter.NewsAdapter;
import per.edward.androidnewsreader.bean.NewsItemModel;public class MainActivity extends Activity {private ListView mListView;private List<String> list;private NewsAdapter adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//初始化视图initView();//初始化数据initData();}public void initView() {list = new ArrayList<String>();mListView = (ListView) findViewById(R.id.list_view);}public void initData() {for (int i = 0; i < 15; i++) {list.add(i+"");}//新闻列表适配器adapter = new NewsAdapter(this, list, R.layout.adapter_news_item);mListView.setAdapter(adapter);//设置点击事件mListView.setOnItemClickListener(new ItemClickListener());}/*** 新闻列表点击事件*/public class ItemClickListener implements AdapterView.OnItemClickListener{@Overridepublic void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {Toast.makeText(getApplicationContext(),""+i,Toast.LENGTH_SHORT ).show();}}
}

activity_main.xml文件如下所示

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"><ListView
        android:id="@+id/list_view"android:layout_width="match_parent"android:layout_height="match_parent"/></RelativeLayout>

adapter_news_item.xml文件如下所示

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:padding="10dp"><ImageView
        android:id="@+id/image_view"android:layout_width="80dp"android:layout_height="wrap_content"android:scaleType="centerCrop"android:layout_centerVertical="true"android:background="@mipmap/ic_launcher" /><LinearLayout
        android:layout_marginLeft="10dp"android:id="@+id/line"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_toRightOf="@+id/image_view"android:orientation="vertical"><TextView
            android:id="@+id/txt_title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Edward"android:textSize="16dp" /><TextView
            android:layout_marginTop="5dp"android:id="@+id/txt_summary"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="岭南学院"android:textSize="12dp" /></LinearLayout></RelativeLayout>

~~~整个界面的效果就是如下图,非常的简单。

整个新闻列表界面搭建完成。就是如此简单。接下来就是分享一下如何去抓取新闻网站的数据。

2. 第二部分,数据抓取分析

抓取目标URL地址:http://news.qq.com/china_index.shtml
下面咋们看看这个网站中的内容,内容中左边有个图片右边有新闻标题和新闻摘要。
接下来目标很明确,就是将这些数据全部拿下来,再将其显示在第一部搭建的界面中。

查看此页面的源代码,如下图所示,我用红色边框勾出了三条新闻的源代码。

<a target="_blank" class="pic" href="/a/20150909/036168.htm"><img class="picto" src="http://img1.gtimg.com/news/pics/hv1/51/43/1920/124859016.jpg"></a><em class="f14 l24"><a target="_blank" class="linkto" href="/a/20150909/036168.htm">英航客机美国拉斯维加斯起火 14人轻伤送医治疗</a></em><p class="l22">美国联邦航空管理局发布声明说,飞机左引擎起火,机组中断起飞,指挥乘客紧急疏散。</p>

我们可以发现,除了新闻的图片地址,新闻标题,新闻的摘要,新闻详情地址会改变之外,其它的标签对都不会改变。因此我们根据此规则,可以简单的使用正则表达式匹配出我们想要的数据出来。
正则表达式的核心代码如下

Pattern pattern = Pattern.compile("<a target=\"_blank\" class=\"pic\" href=\"([^\"]*)\"><img class=\"picto\" src=\"([^\"]*)\"></a><em class=\"f14 l24\"><a target=\"_blank\" class=\"linkto\" href=\"[^\"]*\">([^</a>]*)</a></em><p class=\"l22\">([^</p>]*)</p>");

可以看到compile中字符串里面的内容基本和每条新闻源码相似,其中([^\"]*),([^</a>]*),([^</p>]*)这三个比较奇怪的语句,咋们可以简单的认为在此限定的字符串中任意匹配所有字符直到遇到\”结束。其它两个([^</a>]*),([^</p>]*)也差不多同样的意思。

Function.java文件的代码

package per.edward.androidnewsreader.function;import android.util.Log;import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;import per.edward.androidnewsreader.bean.NewsItemModel;/*** description:解析新闻数据* <p/>* author:Edward* <p/>* 2015/9/9*/
public class Function {public static List<NewsItemModel> parseHtmlData(String result) {List<NewsItemModel> list = new ArrayList<>();Pattern pattern = Pattern.compile("<a target=\"_blank\" class=\"pic\" href=\"([^\"]*)\"><img class=\"picto\" src=\"([^\"]*)\"></a><em class=\"f14 l24\"><a target=\"_blank\" class=\"linkto\" href=\"[^\"]*\">([^</a>]*)</a></em><p class=\"l22\">([^</p>]*)</p>");Matcher matcher = pattern.matcher(result);StringBuffer sb = new StringBuffer();while (matcher.find()) {NewsItemModel model = new NewsItemModel();model.setNewsDetailUrl(matcher.group(1).trim());model.setUrlImgAddress(matcher.group(2).trim());model.setNewsTitle(matcher.group(3).trim());model.setNewsSummary(matcher.group(4).trim());sb.append("详情页地址:" + matcher.group(1).trim() + "\n");sb.append("图片地址:" + matcher.group(2).trim() + "\n");sb.append("标题:" + matcher.group(3).trim() + "\n");sb.append("概要:" + matcher.group(4).trim() + "\n\n");list.add(model);}Log.e("----------------->", sb.toString());return list;}}

NewsItemModel.java

package per.edward.androidnewsreader.bean;import android.graphics.Bitmap;/*** description:新闻Model* <p/>* author:Edward* <p/>* 2015/9/9*/
public class NewsItemModel {//存储加载完成的图片private Bitmap newsBitmap;//新闻详情地址private String newsDetailUrl;//新闻图片地址private String urlImgAddress;//新闻标题private String newsTitle;//新闻概要private String newsSummary;public Bitmap getNewsBitmap() {return newsBitmap;}public void setNewsBitmap(Bitmap newsBitmap) {this.newsBitmap = newsBitmap;}public String getUrlImgAddress() {return urlImgAddress;}public void setUrlImgAddress(String urlImgAddress) {this.urlImgAddress = urlImgAddress;}public String getNewsDetailUrl() {return newsDetailUrl;}public void setNewsDetailUrl(String newsDetailUrl) {this.newsDetailUrl = newsDetailUrl;}public String getNewsTitle() {return newsTitle;}public void setNewsTitle(String newsTitle) {this.newsTitle = newsTitle;}public String getNewsSummary() {return newsSummary;}public void setNewsSummary(String newsSummary) {this.newsSummary = newsSummary;}
}

CommonTool.java代码

package per.edward.androidnewsreader.tool;import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;public class CommonTool {/*** get请求(获取指定地址的数据)** @param urlString* @return*/public static String getRequest(String urlString, String codingType) {BufferedInputStream bis = null;ByteArrayOutputStream bos = null;InputStream is = null;try {URL url = new URL(urlString);HttpURLConnection conn = (HttpURLConnection) url.openConnection();// 决定返回值为JSON格式,不可缺少conn.setRequestProperty("Accept", "*/*");conn.connect();int responseCode = conn.getResponseCode();if (responseCode == 200) {is = conn.getInputStream();bis = new BufferedInputStream(is);bos = new ByteArrayOutputStream();int length = 0;byte[] by = new byte[1024];while ((length = bis.read(by)) != -1) {bos.write(by, 0, length);}bos.flush();String result = new String(bos.toByteArray(), codingType);// System.out.println(result);return result;}} catch (MalformedURLException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {try {if (bos != null) {bos.close();}if (bis != null) {bis.close();}if (is != null) {is.close();}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();System.out.println("关闭失败!");}}return null;}/*** 下载图片网络** @param urlString** @return*/public static InputStream getImgInputStream(String urlString) {try {URL url = new URL(urlString);HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod("GET");   //设置请求方法为GETconnection.setReadTimeout(10 * 1000);    //设置请求过时时间为10秒connection.connect();if (connection.getResponseCode() == 200) {return connection.getInputStream();} else {return null;}} catch (Exception e) {return null;}}}

NewsAdapter.java文件

package per.edward.androidnewsreader.adapter;import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;import java.util.List;import per.edward.androidnewsreader.R;
import per.edward.androidnewsreader.bean.NewsItemModel;/*** description:* <p/>* author:Edward* <p/>* 2015/9/9*/
public class NewsAdapter extends BaseAdapter {private Context mContext;private List<NewsItemModel> list;private int layoutId;private ViewHolder viewHolder = null;public NewsAdapter(Context mContext, List<NewsItemModel> list, int layoutId) {this.mContext = mContext;this.list = list;this.layoutId = layoutId;}@Overridepublic int getCount() {return list.size();}@Overridepublic Object getItem(int i) {return list.get(i);}@Overridepublic long getItemId(int i) {return i;}@Overridepublic View getView(final int position, View view, ViewGroup viewGroup) {if (view == null) {viewHolder = new ViewHolder();view = LayoutInflater.from(mContext).inflate(layoutId, null);viewHolder.imageView = (ImageView) view.findViewById(R.id.image_view);viewHolder.txtTitle = (TextView) view.findViewById(R.id.txt_title);viewHolder.txtSummary = (TextView) view.findViewById(R.id.txt_summary);view.setTag(viewHolder);} else {viewHolder = (ViewHolder) view.getTag();}if (list.get(position).getNewsBitmap() != null) {viewHolder.imageView.setImageBitmap(list.get(position).getNewsBitmap());} else {//如果没有图片,则将imageview控件隐藏viewHolder.imageView.setVisibility(View.GONE);}viewHolder.txtTitle.setText(list.get(position).getNewsTitle());viewHolder.txtSummary.setText(list.get(position).getNewsSummary());return view;}public class ViewHolder {ImageView imageView;TextView txtTitle, txtSummary;}}

最后在进行网络操作之后别忘了AndroidManifest.xml的网络权限。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="per.edward.androidnewsreader"><!--授予网络权限--><uses-permission android:name="android.permission.INTERNET" /><!--最低安装版本--><uses-sdk
        android:maxSdkVersion="22"android:minSdkVersion="9" /><application
        android:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:theme="@style/AppTheme"><activity
            android:name=".MainActivity"android:label="@string/app_name"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>

最后再修改一下第一部分贴过的MainActivity.java文件的代码。

package per.edward.androidnewsreader;import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;import java.util.ArrayList;
import java.util.List;import per.edward.androidnewsreader.adapter.NewsAdapter;
import per.edward.androidnewsreader.bean.NewsItemModel;
import per.edward.androidnewsreader.function.Function;
import per.edward.androidnewsreader.tool.CommonTool;public class MainActivity extends Activity {private ListView mListView;private List<NewsItemModel> list;private NewsAdapter adapter;//获取数据成功private final static int GET_DATA_SUCCEED = 1;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//初始化视图initView();//初始化数据initData();}public void initView() {list = new ArrayList<NewsItemModel>();mListView = (ListView) findViewById(R.id.list_view);}public void initData() {//开启一个线程执行耗时操作new Thread(new Runnable() {@Overridepublic void run() {//获取网络数据String result = CommonTool.getRequest("http://news.qq.com/china_index.shtml", "gbk");Log.e("结果------------->", result);//解析新闻数据List<NewsItemModel> list = Function.parseHtmlData(result);for (int i = 0; i < list.size(); i++) {NewsItemModel model = list.get(i);//获取新闻图片Bitmap bitmap = BitmapFactory.decodeStream(CommonTool.getImgInputStream(list.get(i).getUrlImgAddress()));model.setNewsBitmap(bitmap);}mHandler.sendMessage(mHandler.obtainMessage(GET_DATA_SUCCEED, list));}}).start();}public Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case GET_DATA_SUCCEED:List<NewsItemModel> list = (List<NewsItemModel>) msg.obj;//新闻列表适配器adapter = new NewsAdapter(MainActivity.this, list, R.layout.adapter_news_item);mListView.setAdapter(adapter);//设置点击事件mListView.setOnItemClickListener(new ItemClickListener());Toast.makeText(getApplicationContext(), String.valueOf(list.size()), Toast.LENGTH_LONG).show();break;}}};/*** 新闻列表点击事件*/public class ItemClickListener implements AdapterView.OnItemClickListener {@Overridepublic void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {NewsItemModel temp =(NewsItemModel) adapter.getItem(i);Toast.makeText(getApplicationContext(), temp.getNewsTitle(), Toast.LENGTH_SHORT).show();}}
}

Demo的最终效果图

程序源码请戳这里

Android新闻阅读器(数据抓取)相关推荐

  1. 基于android新闻阅读器,Readian News是一款基于Android和网络的新闻阅读器,可让您掌控一切...

    主流媒体有其用途,但这些新闻出版物在很大程度上忽略了许多主题和兴趣.想要跟上赛博朋克2077游戏,Mozilla Firefox的Proton设计更新或您最喜欢的足球运动员西蒙·恩格尔曼(Simon ...

  2. android在线查询音乐,Android 数据抓取——在线音乐播放器的实现

    前言: 相信很多同学学习android都开做过播放器一类的小玩意吧,但是苦于没有服务器提供数据,因而只能做个本地播放器,今天,这篇文章就是通过数据抓取,实现没有服务器,依然可以在线搜索和播放音乐! 首 ...

  3. (android高仿系列)今日头条 --新闻阅读器 (二)

    高仿今日头条 --- 第一篇:(android高仿系列)今日头条 --新闻阅读器 (一) 上次,已经完成了头部新闻分类栏目的拖动效果. 这篇文章是继续去完善APP 今日头条  这个新闻阅读器的其他功能 ...

  4. cookie追加数据_集算器 SPL 抓取网页数据

    [摘要] 集算器 SPL 支持抓取网页数据,根据抓取定义规则,可将网页数据下载到在本地进行统计分析.具体定义规则要求.使用详细情况,请前往乾学院:集算器 SPL 抓取网页数据! 网站上的数据源是我们进 ...

  5. jQuery Mobile发展新闻阅读器,适应iphone和android打电话

    程序猿是很不赖,你知道. 我们经常新浪,腾讯.雅虎等各大网站看到上述新闻.他们还推出了自己的移动新闻阅读器.今天,我自己用的jQuery Mobile 为了实现这一功能,.图像大小上传限制的大小250 ...

  6. Android 仿 新闻阅读器 菜单弹出效果(附源码DEMO)

    这一系列博文都是:(android高仿系列)今日头条 --新闻阅读器 (一) 开发中碰到问题之后实现的,觉得可能有的开发者用的到或则希望独立成一个小功能DEMO,所以就放出来这么一个DEMO. 原本觉 ...

  7. jQuery Mobile开发的新闻阅读器,适应iphone和android手机

    程序猿都非常赖.你懂的! 我们常常上新浪,腾讯.雅虎等各大站点上面看新闻.他们也都各自推出了自家的手机新闻阅读器.今天我自己使用jQuery Mobile 来实现这一功能.图片大小上传限制了大小250 ...

  8. 高校新闻抓取分析之百度新闻篇---数据抓取

    高校新闻抓取分析之百度新闻篇-数据抓取 tips: 本文代码使用python3编写 代码仓库 使用urllib抓取数据 百度新闻网页界面分析 在我读大学的时候(18年前),百度新闻还能基于新闻标题或者 ...

  9. (android高仿系列)今日头条 --新闻阅读器 (一)

    在模仿中循序渐进,以程序员角度去看待每一个APP是如何实现的,它有什么优缺点,并从中提升自己. 之前发现很多人在群里面.论坛上求网易新闻客户端的源码,之后我就去下了个网易新闻客户端和今日头条新闻客户端 ...

最新文章

  1. boseqc35能不能连电脑_连win7都用不了?轻量级LXLE系统,只要10分钟,旧电脑也能运行如飞!...
  2. 三十七、Sql 补充 | 数据库优化
  3. 嘘!阿里程序媛上班的第一件事是...
  4. Android之运行PopupWindow提示Unable to add window -- token null is not valid; is your activity running?
  5. 多进程修改全局变量(python版)
  6. 卡尔曼滤波对gps轨迹数据清洗_基于GPS的智能交通系统车辆定位精度提升技术
  7. 分类型变量预测连续型变量_「JS进阶」你真的掌握变量和类型了吗
  8. sql如何取前几行_重磅!蚂蚁金服开源机器学习工具SQLFlow,机器学习比SQL还简单...
  9. element ui 点击修改开启停用按钮状态
  10. js 自定义 $ 选择器
  11. 网络安全-应急响应之入侵排查篇及相关工具
  12. Solr全文检索学习笔记·记录
  13. [Python从零到壹] 十八.可视化分析之Basemap地图包入门详解
  14. 分析微博游戏名人数据
  15. SQL语法——触发器
  16. 记一次项目经验(4)
  17. ico付费图标下载器 附带易语言源码
  18. SDI Over IP相关标准及技术简介
  19. 小柯印前设计师(DrawVBA)及教程
  20. 代码坏的味道17:狎昵关系 (Inappropriate Intimacy)

热门文章

  1. java后端语言_后端程序员一定要看的语言大比拼:Java vs. Go vs. Rust
  2. Oracle 字符串比较大小
  3. JAVA基础4万字超详细总结
  4. python爬图片显示不了_Python爬取网页中的图片(搜狗图片)详解
  5. 手机端的操作手势——touch.js
  6. life in a day
  7. 计算机软件版本号是什么意思,如何查看软件名称和版本号
  8. printf中%m.nd, %m.ns, %m.nf的输出规则
  9. 除了双机或多机热备,你还该有其他方法解决集群路由机宕机(双机热备)
  10. sql中时间判断符号_大于号_小于号