当前位置:首页 >> 工学 >>

安卓课程设计——新闻客户端(基于网页抓取)


题目 android 课程设计——新闻客户端

姓名: 学号: 专业: 学院: 指导教师:

二零一八年十一月

一、需求分析
启动程序后可以进行新闻资讯的实时更新,可分不同的栏目让使用者了解任 意感兴趣的资讯进行阅读, 启动程序后可以进行新闻资讯的实时更新,可分不同 的栏目让使用者了解任意感兴趣的资讯进行阅读。 1)启动应用程序; 2)设置界面:采用多种布局嵌套,美化控件。 3)显示界面:模仿网易新闻客户端进行 UI 编写。 4)详细界面:分为头条、国内、国际、财经、科技、社会等板块 从用户的角度出发,针对用户的需求,所涉及的程序响应速度快、信息处理 速度快、安全性高是用户所需要的三大主要性能,另外为了受众面更广,根据目 前的 android 设备系统版本的分布情况,android2.3 以上的版本占到设备总量 的 80% 以 上 , 所 以 做 开 发 的 时 候 选 择 的 android 系 统 最 低 版 本 也 必 须 是 android2.3 以上来保证用户量。

二、概要设计
(一)开发环境 采用 windows+Eclipse+ADT 的环境进行开发, 在 Android2.3 以上版本的系统 中运行的。 (二)系统流程 软件分为了两大模块,分别是新闻客户端模块和服务器模块。

a)客户端 顾名思义就是前台框架设计,模仿了网易新闻的 app ,界面设计参考的是 github 网站的前辈;

备注:打开后界面默认为“头条”界面

b)服务器 这里值得一提的是做成了抓取各新闻网站,解析出新闻呈现给前台,用的是 jsoup.jar 获取和 htmlparser.jar 解析,有点复杂了,但还好有使用方法,能 直接拿过来用。 1. jsoup.jar 获取
(参考:http://www.open-open.com/jsoup)

将下载下来的 jar 包放到放到 Android 工程中 libs 目录下, 加以编写即可:
String html = "<html><head><title>First parse</title></head>" + "<body><p>Parsed HTML into a doc.</p></body></html>"; Document doc = Jsoup.parse(html);

上面这个例子比较简单,直接就将 html 转换成 Document 实例了,之后再解 析 2. htmlparser.jar 解析
(参考:http://www.cnblogs.com/coding-hundredOfYears/archive/2012/12/15/2819217.html)

网页解析模块要实现两大功能: 1.从页面中提取出子链接,加入到爬取 url 队列中; 2.解析网页内容,与主题进行相关度计算。 具体步骤如下: a.读取 html 文件,获得页面编码,获得 String 格式的文件内容 b.用页面编码实例化 html 文件的 Parser c.对需要提取的结点设置相应的 Filter d.根据给定的 Filter,用 Parser 解析 html 文件 e.提取结点中的文本内容,进行处理

三、设计与实现
(一)布局设计 主要设计了三个界面:全局界面、新闻列表显示界面、详细新闻界面

a. 全局界面(main.xml)

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/

android" xmlns:tools="http://schemas.android.com/tools"

android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/bg_title_bar" android:orientation="vertical" tools:context=".Main" > <LinearLayout android:id="@+id/title_layout" android:layout_width="fill_parent" android:layout_height="20dp" android:background="@drawable/public_titlebar_bg" android:orientation="horizontal" > <TextView android:id="@+id/textView_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:text="@string/app_name" android:textColor="#000" android:textSize="12sp" /> </LinearLayout> <LinearLayout android:id="@+id/main_type_title" android:layout_width="wrap_content" android:layout_height="50dip" android:layout_gravity="center_vertical" android:orientation="horizontal" > <HorizontalScrollView android:id="@+id/main_scroll" android:layout_width="0dip" android:layout_height="50dip" android:layout_weight="1" android:scrollbars="none" > <LinearLayout

android:id="@+id/main_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:orientation="horizontal" > </LinearLayout> </HorizontalScrollView> <Button android:id="@+id/main_speak" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginLeft="10dip" android:layout_marginRight="10dip" android:background="@drawable/bg_read_button_selec t" android:gravity="right|center_vertical" android:paddingRight="10dip" android:text="@string/button_text_read" android:textColor="#FFFFFFFF" /> </LinearLayout> <android.support.v4.view.ViewPager android:id="@+id/main_page" android:layout_width="wrap_content" android:layout_height="0dp" android:layout_weight="1" android:background="#FF000000" /> </LinearLayout>

b.新闻列表显示界面(list_item.xml) ListView 是 Android 系统自带的控件之一,它的使用同样是十分广泛的,它 通常用来加载一系列相同布局的列表。使用它同样需要一个 PagerAdapter 适配 器来给它提供数据。 从新闻列表的特征来看, 显然是由一个 ListView 来实现的。 但是为了在滑动 ListView 的时候,带动 ViewPager 一起滑动,则需要自定义一 个控件,来讲广告轮播条的 ViewPager 和新闻列表的 ListView 关联起来。而大 部分的新闻软件都有上拉刷新和下拉加载更多的功能, 所以在此自定义控件中也 应加上上拉刷新和下拉加载更多的功能。此自定义控件继承了 ListView 类,实 现 了 OnScrollListener,android.widget.AdapterView.OnItemClickListener 接口。 c.详细新闻界面(detail.xml) 新闻详情页即是点击新闻进入后的页面,使用一个 ScrollView 来实现。在新 闻详情页中,用户可以点击返回按钮返回到前一页面。

(二)功能实现

a.主新闻页面的设计与实现 定义出页面所需要用到的控件以及新闻栏目的适配器(如右图) ,然后初始化 界面布局、标题等:
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.main); initLayout(); initViewPage(); initTitle();

}

b. 新闻详细页面的设计与实现:

c.数据接口:
public class DataAdapter extends BaseAdapter { Context mContext = null; LayoutInflater inflater; List<NewsBrief> newsData = new ArrayList<NewsBrief>(); public DataAdapter(Context context, List<NewsBrief> nList) { mContext = context; inflater = LayoutInflater.from(context); newsData = nList; }

@Override public int getCount() { return newsData.size(); } @Override public Object getItem(int arg0) { return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { HolderView hView = null; if (null == convertView) { hView = new HolderView(); convertView = inflater.inflate(R.layout.list_item, null); hView.image = (ImageView)convertView.findViewById(R.id.news_imag e); hView.speak = (ImageView)convertView.findViewById(R.id.news_spea k); hView.title = (TextView)convertView.findViewById(R.id.news_title ); hView.brief = (TextView)convertView.findViewById(R.id.news_brief ); hView.where = (TextView)convertView.findViewById(R.id.news_where ); hView.date = (TextView)convertView.findViewById(R.id.news_time) ; convertView.setTag(hView); } else { hView = (HolderView) convertView.getTag(); } hView.title.setText(newsData.get(position).g etTitle()); if(!"".equals(newsData.get(position).getCont ent()) && newsData.get(position).getContent().length()>26){ String str=newsData.get(position).getContent().trim().sub string(0, 24);

r));

hView.brief.setText(NetUtil2.replaceBlank(st } else { hView.brief.setText(""); }

if (NetUtil2.CURRENT_SPEAK.equals(newsData.get(positi on).getUrl())) { hView.speak.setVisibility(View.VISIBLE); hView.title.setTextColor(Color.RED); } else { hView.speak.setVisibility(View.GONE); hView.title.setTextColor(Color.WHITE); } hView.where.setText(newsData.get(position).g etSource()); hView.date.setText(newsData.get(position).ge tPubDate()); if (null newsData.get(position).getImgUrl() !=

&& !"".equals(newsData.get(position).getImgU rl())) { hView.image.setTag(newsData.get(position).ge tImgUrl()); ImageLoader2.getInstance(mContext).loadImage (newsData.get(position).getImgUrl(), hView.image); } else { hView.image.setImageResource(R.drawable.icon _image_default); } return convertView; } public class HolderView { private ImageView image = null; private ImageView speak = null; private TextView title = null; private TextView brief = null; private TextView where = null; private TextView date = null; } }

d.数据获取:

利用 jsoup 和 htmlparser 抓紧并解析新闻,下面为解析腾讯新闻页面:
public class NetUtil { public static List<NewsBrief> DATALIST = new ArrayList<NewsBrief>(); public static String[][] CHANNEL_URL = new String[][] { new String[]{"http://news.qq.com/world_index.shtml","h ttp://news.qq.com"}, new String[]{"http://news.qq.com/china_index.shtml","h ttp://news.qq.com"}, new String[]{"http://news.qq.com/society_index.shtml", "http://news.qq.com"}, new String[]{"http://news.qq.com/china_index.shtml","h ttp://news.qq.com"},

new String[]{"http://news.qq.com/china_index.shtml","h ttp://news.qq.com"}, new String[]{"http://news.qq.com/china_index.shtml","h ttp://news.qq.com"}, new String[]{"http://news.qq.com/china_index.shtml","h ttp://news.qq.com"}, new String[]{"http://news.qq.com/china_index.shtml","h ttp://news.qq.com"}, new String[]{"http://news.qq.com/china_index.shtml","h ttp://news.qq.com"}, new String[]{"http://news.qq.com/china_index.shtml","h ttp://news.qq.com"}, new String[]{"http://news.qq.com/china_index.shtml","h ttp://news.qq.com"}, }; public static int getTechNews(List<NewsBrief> techData, int cId) { int result = 0; try { NodeFilter filter = new AndFilter(new TagNameFilter("div"), new HasAttributeFilter("id", "listZone")); Parser parser = new Parser(); parser.setURL(CHANNEL_URL[cId][0]); parser.setEncoding(parser.getEncoding()); NodeList list = parser.extractAllNodesThatMatch(filter); for (int i = 0; i < list.size(); i++) { Tag node = (Tag) list.elementAt(i); for (int j = 0; j < node.getChildren().size(); j++) { try { String textstr = node.getChildren().elementAt(j).toHtml(); if (textstr.trim().length() > 0) { NodeFilter subFilter = new TagNameFilter("p"); Parser subParser = new Parser(); subParser.setResource(textstr); NodeList subList = subParser.extractAllNodesThatMatch(subFilter); NodeFilter titleStrFilter = new AndFilter(new TagNameFilter("a"), new HasAttributeFilter("class", "linkto")); Parser titleStrParser = new Parser(); titleStrParser.setResource(textstr); NodeList titleStrList = titleStrParser.extractAllNodesThatMatch(titleStrFi lter); int linkstart = titleStrList.toHtml().indexOf("href=\""); int linkend = titleStrList.toHtml().indexOf("\">"); int titleend = titleStrList.toHtml().indexOf("</a>"); String link = CHANNEL_URL[cId][1]+titleStrList.toHtml().substrin g(linkstart+6, linkend); String title = titleStrList.toHtml().substring(linkend+2, titleend);

NewsBrief newsBrief = new NewsBrief(); newsBrief.setTitle(title); newsBrief.setUrl(link); newsBrief.setSummary(subList.asString()); techData.add(newsBrief); } } catch (Exception e) { e.printStackTrace(); }

} } } catch (Exception e) { result = 1; e.printStackTrace(); } return result; }

public static int getTechNews2(List<NewsBrief> techData, int cId) { int result = 0; try { // 查询 http://tech.qq.com/tech_yejie.htm 页面 滚动新闻的 标签 以及 ID NodeFilter filter = new AndFilter(new TagNameFilter("div"), new HasAttributeFilter("id", "listZone")); Parser parser = new Parser(); parser.setURL(CHANNEL_URL[cId][0]); parser.setEncoding(parser.getEncoding()); // 获取匹配的 fileter 的节点 NodeList list = parser.extractAllNodesThatMatch(filter); StringBuilder NewsStr = new StringBuilder("<table>");// 新闻表格字符串 for (int i = 0; i < list.size(); i++) { Tag node = (Tag) list.elementAt(i); for (int j = 0; j < node.getChildren().size(); j++) { String textstr = node.getChildren().elementAt(j).toHtml() .trim(); if (textstr.length() > 0) { int linkbegin = 0, linkend = 0, titlebegin = 0, titleend = 0; while (true) { linkbegin = textstr.indexOf("href=", titleend);// 截取链接字符 串起始位置 // 如果不存在 href 了 也就结束了 if (linkbegin < 0) break; linkend = textstr.indexOf("\">", linkbegin);// 截取链接字符 串结束位置 String sublink = textstr.substring(linkbegin + 6,linkend); String link = CHANNEL_URL[cId][1] + sublink; titlebegin = textstr.indexOf("\">", linkend); titleend = textstr.indexOf("</a>", titlebegin); String title = textstr.substring(titlebegin + 2,titleend); NewsStr.append("\r\n<tr>\r\n\t<td><a target=\"_blank\" href=\"" "\">"); + link +

NewsStr.append(title); NewsStr.append("</a></td></tr>"); NewsBrief newsBrief = new NewsBrief(); newsBrief.setTitle(title); newsBrief.setUrl(link); techData.add(newsBrief); } } } } } catch (Exception e) { result = 1; e.printStackTrace(); } return result; } public static int parserURL(String url,NewsBrief newsBrief) { int result = 0; try { Parser parser = new Parser(url); NodeFilter contentFilter = new AndFilter( new TagNameFilter("div"), new HasAttributeFilter("id","Cnt-Main-Article-QQ")); NodeFilter newsdateFilter = new AndFilter( new TagNameFilter("span"), new HasAttributeFilter("class", "article-time")); NodeFilter newsauthorFilter = new AndFilter( new TagNameFilter("span"), new HasAttributeFilter("class", "color-a-1")); NodeFilter imgUrlFilter = new TagNameFilter("IMG"); newsBrief.setContent(parserContent(contentFilter,p arser)); parser.reset(); // 记得每次用完 parser 后,要重置一次 parser。要不然就得不到我们想要 的内容了。 newsBrief.setPubDate(parserDate(newsdateFilter,par ser)); parser.reset(); newsBrief.setSource(parserAuthor(newsauthorFilter, parser)); parser.reset(); newsBrief.setImgUrl(parserImgUrl(contentFilter,img UrlFilter, parser)); } catch (Exception e) { result=1; e.printStackTrace(); } return result; } private static String parserContent(NodeFilter filter, Parser parser) { String reslut = ""; try { NodeList contentList = (NodeList) parser.parse(filter); // 将 DIV 中的标签都 去掉只留正文 reslut = contentList.asString(); } catch (Exception e) { e.printStackTrace();

}

} return reslut;

private static String parserDate(NodeFilter filter, Parser parser) { String reslut = ""; try { NodeList datetList = (NodeList) parser.parse(filter); // 将 DIV 中的标签都 去掉只留正文 reslut = datetList.asString(); } catch (Exception e) { e.printStackTrace(); } return reslut; } private static String parserAuthor(NodeFilter filter, Parser parser) { String reslut = ""; try { NodeList authorList = (NodeList) parser.parse(filter); // 将 DIV 中的标签都 去掉只留正文 reslut = authorList.asString(); } catch (Exception e) { e.printStackTrace(); } return reslut; } private static List<String> parserImgUrl(NodeFilter bodyfilter,NodeFilter filter, Parser parser) { List<String> reslut = new ArrayList<String>(); try { NodeList bodyList = (NodeList) parser.parse(bodyfilter); Parser imgParser = new Parser(); imgParser.setResource(bodyList.toHtml()); NodeList imgList = imgParser.extractAllNodesThatMatch(filter); String bodyString = imgList.toHtml(); //正文包含图片 if (bodyString.contains("<IMG") && bodyString.contains("src=")) { if(imgList.size()>0){ for(int i=0;i<imgList.size();i++){ String imgString = imgList.elementAt(i).toHtml(); int imglinkstart = imgString.indexOf("src=\""); int imglinkend = imgString.indexOf(">"); if(imgString.contains("\" alt=")){ imglinkend = imgString.indexOf("\" alt="); } if(imgString.contains("_fck")){ imglinkend = imgString.indexOf("_fck");// 截取链接字符串结束位 置 } reslut.add(imgString.substring(imglinkstart + 5, imglinkend)); } } } } catch (Exception e) { e.printStackTrace(); } return reslut; } }

四、运行画面截图

1.图标截图: 2.运行截图:

五、心得体会
拿到课题后,自己主动粗略设计了大概方向,但有很多问题不是很清楚,所 以做起来就就很困难, 刚开始的时候都有点无从下手的感觉。很多时候在遇到问 题时,基本知识都了解,但是就不知道怎么才能把它们都整合到一块,也就是说 知识都是很零散的,没有一个完整的系统。而且,又由于基础知识不牢固,使得 我在这次的课程设计中感到更加力不从心。 一开始,我在考虑一般的新闻客户端要设计服务器自定义新闻内容,凭什么 能说是新闻呢?然后在设计抓取页面时,jsoup 和 htmlparser 两个包并不能充 分理解和使用,这很让我头大,毕竟休学回来不久。结合自己的实际,虽然不能 完整的实现 app 功能,但我还是做出来一个大概的 app,有待日后完善。 在设计的过程中,每走一步就会发现,思路想出来很容易,但涉及到实现的 时候, 总是有点手无足措。 对于本次的课程设计, 里面还有很多需要改进的地方。 一个程序的顺利出炉,少不了反复地调试和修改。在调试的过程中,总是会发生 很多错误,但在解决这些错误的时候,开始很模糊的概念就会变得越来越清晰。 其实很多错误都是很类似的,只要解决了一个,其余的就会迎刃而解了。


赞助商链接
相关文章:
基于Android平台的新闻客户端的设计与实现_图文
端软件是基于 Android 手机平台, 采用 Java 语言, 从网络上的开放的新闻接口获取数据,设计出针对使用 Android 平台的手机新闻 客户端资讯实时掌控的手机应用程序。 ...
新闻客户端报告
客户端软件是基于 Android 手机平台, 采用 Java 语言,从网络上的开放的新闻接口获取数据,设计出针对 使用 Android 平台的手机新闻客户端资讯实时掌控的手机应用程序...
基于Android的新闻客户端_毕业设计说明书
下载客户端 | 百度首页 | 登录注册新闻 网页 贴吧...基于 Android新闻客户端获取新闻更加便携,内容...程序库和运行库(Libraries 和 Runtime):这一层主要...
基于Android平台的新闻客户端的设计与实现毕业论文_图文
毕业论文 基于 Android 平台的新闻客户端设计与...且快捷地获取最新的新闻资讯信息,了解新闻时事, 本...2.2 可行性分析开发任何一个基于手机的应用程序,...
Android应用课程设计题目
Android 应用与开发课程设计题目注意事项: 1、小组可...3. 能在手机或者网页上显示地图轨迹 实现要求:在线...新闻客户端、Zaker 等 实现要求:客户端基于 Android...
新闻网页设计报告
新闻网页设计报告_互联网_IT/计算机_专业资料。课程...的主要方法与技术该系统基于 B/S 运行模式,采用 ...数据库客户端 项目开发工具 服务器程序 网页浏览器 ...
基于android平台的新闻阅读软件的设计与实现开题报告
下载客户端 | 百度首页 | 登录注册新闻网页贴吧知道...基于android平台的新闻阅读软件的设计与实现开题报告_...利用 Wireshark 进行抓包,获取数据源。Wireshark(前...
广东海洋大学软件工程课程设计报告书_图文
本文描述了基于 Android 平台的新闻客户端设计与...传统的热门门户网站:网易、腾讯、新浪、 搜狐等业内...(2)海量获取:同以往的报纸,杂志,新闻周刊等传统...
课程设计_参考封面和目录_图文
《Web 课程设计》报告学 院: 信息工程学院 ...基于安卓平台的新闻客户端开发 1 题目简介 ...(6)获取详细新闻功能; (7)异步加载新闻内容...
安卓手机应用程序设计毕业论文
下载客户端 | 百度首页 | 登录注册新闻 网页 贴吧...河南科技大学本科毕业设计(论文) 基于 Android 的...能够帮他获取、获得用户,帮助移动 互联网的用户,...
更多相关标签: