仿CSDN安卓客户端(二)-----从网络上获取并解析html文件
2015-10-10 17:09
525 查看
首先先上一下安卓客户端的效果,之前是静态的图片,不够形象,上一个动态图提升一下逼格。嘿嘿
因为我们使用jsoup解析html文件,所以记得在lib里面添加一下jsoup-1.7.2.jar
下载地址:http://download.csdn.net/detail/start_baby/5132499
今天我们的任务就是从CSDN网站上获取每一个条目相应的目录列表,先贴一下代码,然后我们通过代码来理清思路
我们首先要定义一个新闻目录类,用来存储获取到的每一个新闻
NewsItem.java
定义好了数据类型,我们现在就可以放心的获取网上的数据,这样就不要担心这些数据无家可归了。下面你可以通过注释理解代码,我尽量为你解释每一行代码。
下面开始测试一下上面的NewsItemBiz类,特别注意使用上面类,要使用异步任务,因为在主线程中获取List耗了很长的时间,如果不使用,会导致UI线程卡死,不信的话,你可以试一试哦,我把我之前没有用异步任务的代码也列在了下面,方便你比较这两者的差别吧!
效果图还是要上一下的,不然说我骗人就不好了
点击上面的send,然后观察logcat中的结果
这一节关于从网络上获取并解析html文件我们就先讲到这里,看别人做一万遍,也不如自己做一遍,自己试着做一遍吧!相信自己,你可以的,加油!
因为我们使用jsoup解析html文件,所以记得在lib里面添加一下jsoup-1.7.2.jar
下载地址:http://download.csdn.net/detail/start_baby/5132499
今天我们的任务就是从CSDN网站上获取每一个条目相应的目录列表,先贴一下代码,然后我们通过代码来理清思路
我们首先要定义一个新闻目录类,用来存储获取到的每一个新闻
NewsItem.java
public class NewsItem { private int id; /** * 标题 */ private String title; /** * 链接 */ private String link; /** * 发布日期 */ private String date; /** * 图片的链接 */ private String imgLink; /** * 内容 */ private String content; /** * 类型 * */ private int newsType; public int getNewsType() { return newsType; } public void setNewsType(int newsType) { this.newsType = newsType; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getLink() { return link; } public void setLink(String link) { this.link = link; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } public String getImgLink() { return imgLink; } public void setImgLink(String imgLink) { this.imgLink = imgLink; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } @Override public String toString() { return "NewsItem [id=" + id + ", title=" + title + ", link=" + link + ", date=" + date + ", imgLink=" + imgLink + ", content=" + content + ", newsType=" + newsType + "]"; } }
定义好了数据类型,我们现在就可以放心的获取网上的数据,这样就不要担心这些数据无家可归了。下面你可以通过注释理解代码,我尽量为你解释每一行代码。
NewsItemBiz.java package com.example.httputil; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.List; import org.jsoup.Jsoup; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import com.example.myapplication.myApplication; import android.content.Context; import android.os.Handler; import android.os.Message; import android.provider.DocumentsContract.Document; import android.util.Log; public class NewsItemBiz { //定义一个NewsItem类型的数组 List<NewsItem> newsItems = new ArrayList<NewsItem>(); private int newsType; public NewsItemBiz() { // TODO Auto-generated constructor stub /* * 这里我通过handler机制来控制进程的先后顺序,这是一个很必要的工作,也是我之前碰到的问题得出来的经验,问题大概是这样的: * 因为网络请求数据必须创建一个线程,否则会导致主UI卡死。所以我们创建了一个线程,并且将 * 返回来的数据变成字符串的形式进行处理,然后我们在主线程中需要解析这个字符串 * ,这时候问题就出现了,当子线程请求网络数据还没有结束的时候,主线程就已经开始解析了 * ,这时候这个字符串肯定为空,就会产生错误,所以一定要使用这个异步消息机制 */ public Handler handler=new Handler() { public void handleMessage(android.os.Message msg) { NewsItem newsItem = null; org.jsoup.nodes.Document doc = Jsoup.parse(msg.obj.toString()); Elements units = doc.getElementsByClass("unit"); for (int i = 0; i < units.size(); i++) { newsItem = new NewsItem(); newsItem.setNewsType(newsType); Element unit_ele = units.get(i); Element h1_ele = unit_ele.getElementsByTag("h1").get(0); Element h1_a_ele = h1_ele.child(0); String title = h1_a_ele.text(); String href = h1_a_ele.attr("href"); Log.i("hello",title); newsItem.setLink(href); newsItem.setTitle(title); Element h4_ele = unit_ele.getElementsByTag("h4").get(0); Element ago_ele = h4_ele.getElementsByClass("ago").get(0); String date = ago_ele.text(); newsItem.setDate(date); Element dl_ele = unit_ele.getElementsByTag("dl").get(0);// dl Element dt_ele = dl_ele.child(0);// dt try {// 可能没有图片 Element img_ele = dt_ele.child(0); String imgLink = img_ele.child(0).attr("src"); newsItem.setImgLink(imgLink); } catch (IndexOutOfBoundsException e) { } Element content_ele = dl_ele.child(1);// dd String content = content_ele.text(); newsItem.setContent(content); newsItems.add(newsItem); } }; }; //此函数才是真正被调用的函数,第一个参数是当前页面的类型,第二个参数是页数 public List<NewsItem> getNewsItems( int newsType , int currentPage) throws CommonException, IOException { //通过当前页面类型和页数构造出真正的网址 String urlStr = URLUtil.generateUrl(newsType, currentPage); //将之前的数组清空 newsItems.clear(); doGet(urlStr); /* * 下面的while循环很有必要,因为当子线程还有没有返回字符串时,那么handler就没有办法解析html的时候, * 有可能你的主线程已经走到了下面的一句return * newsItems,那么毫无意外,你就只能得到一个空的newsItems,这就是心急吃不了热豆腐啊 * ,所以我们就要判断newsitems是不是为空,如果是空的话,我们就用一个线程等待 */ while((newsItems.size()==0)) { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return newsItems; } //此函数用来获取一个网页的html数据,并将其变成字符串格式 public void doGet(final String urlStr) throws CommonException{ final StringBuffer sb = new StringBuffer(); new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub try { URL url = new URL(urlStr); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); conn.setDoInput(true); conn.setDoOutput(true); if(conn.getResponseCode() == 200){ InputStream is = conn.getInputStream(); int len = 0; byte[] buf = new byte[1024]; while((len = is.read(buf)) != -1){ sb.append(new String(buf, 0, len, "UTF-8")); } Message message =new Message(); message.obj=sb; handler.sendMessage(message); is.close(); }else{ throw new CommonException("访问网络失败00"); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); try { throw new CommonException("访问网络失败11"); } catch (CommonException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } }).start(); } }
下面开始测试一下上面的NewsItemBiz类,特别注意使用上面类,要使用异步任务,因为在主线程中获取List耗了很长的时间,如果不使用,会导致UI线程卡死,不信的话,你可以试一试哦,我把我之前没有用异步任务的代码也列在了下面,方便你比较这两者的差别吧!
public class secondFragment extends android.support.v4.app.Fragment{ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub View v=inflater.inflate(R.layout.secondfragment, container,false); Button button=(Button)v.findViewById(R.id.send); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { new LoadDatasTask().execute(); //下面就是我之前在主线程中使用的代码,你只需将下面带//的去除,将上面一行加上// // NewsItemBiz newitembiz=new NewsItemBiz(); // List<NewsItem> item=new ArrayList<NewsItem>(); // try { // try { // item=newitembiz.getNewsItems(3, 2); // for (NewsItem newsItem : item) { // Log.i("msg", newsItem.getContent()); // } // } catch (CommonException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } // } catch (IOException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } } }); return v; } class LoadDatasTask extends AsyncTask<Void, Void, Void> { public NewsItemBiz newitembiz=new NewsItemBiz(); public List<NewsItem> item=new ArrayList<NewsItem>(); protected void onPostExecute(Void result) { for (NewsItem newsItem : item) { Log.i("msg", newsItem.getContent()); } } @Override protected Void doInBackground(Void... params) { // TODO Auto-generated method stub try { try { item=newitembiz.getNewsItems(3, 2); } catch (CommonException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } return null; } } }
效果图还是要上一下的,不然说我骗人就不好了
点击上面的send,然后观察logcat中的结果
这一节关于从网络上获取并解析html文件我们就先讲到这里,看别人做一万遍,也不如自己做一遍,自己试着做一遍吧!相信自己,你可以的,加油!
相关文章推荐
- API Hooking with MS Detours-http://www.codeproject.com/Articles/30140/API-Hooking-with-MS-Detours
- centOS7网络配置
- iOS9更新后无法使用AFNetWorking执行http请求的问题
- tcp数据包接收
- Linux集群-负载均衡lvs介绍及lvs-nat实现https
- 获得Android系统的唯一标识、android版本、网络接入方式、当前网络接入方式的MAC地址、IP、CPU的利用率、CPU的负载、内存大小
- Java网络编程
- WebApi学习总结系列第三篇(Http)此篇持续更新...
- 使用RTP over RTSP(TCP)
- 【iOS网络通信】socket第三方库 AsyncSocket(GCDAsyncSocket)
- get与post区别 我同意这种说法
- 《UNIX网络编程》例子程序中所使用的包裹函数及部分常量
- Xcode7 使用NSURLSession发送HTTP请求的问题
- java web 将http 强转为https
- Java套接字(Socket)网络编程入门
- HTTP 错误 404.3 - Not Found 由于扩展配置问题而无法提供您请求的页面。如果该页面是脚本,请添加处理程序。如果应下载文件,请添加 MIME 映射。
- HTTPS概述
- C#高级篇(三)---Socket 、TcpClient 、UdpClient
- [IOS 开发] AFNetworking2.2 setReachabilityStatusChangeBlock检测网络连接状态
- 神经网络学习(一)