Android实战:手把手实现“捧腹网”APP(一)-----捧腹网网页分析、数据获取
Android实战:手把手实现“捧腹网”APP(一)—–捧腹网网页分析、数据获取
Android实战:手把手实现“捧腹网”APP(二)—–捧腹APP原型设计、实现框架选取
Android实战:手把手实现“捧腹网”APP(三)—–UI实现,逻辑实现
“捧腹网”页面结构分析
捧腹网M站地址: http://m.pengfu.com/
捧腹网M站部分截图:
从截图中(可以直接去网站看下),我们可以看出,该网站相对简单,一共分为四个模块:最新笑话、捧腹段子、趣图、神回复。 然后页面的显示形式有两种,一是单纯的文字(段子),二是单纯的图片(趣图)。其中趣图又分为静态图片和动态图片(gif图),且趣图的显示比段子多了“标签”。
“捧腹网”网页源码分析
在网页中点击右键,点击弹出菜单中的“查看网页代码”,就可以查看到当前网页的源代码。查看源代码,我们可以看出,每一个笑话,都是一个list-item。我截取部分代码,给大家略作分析。
我在上图中已经进行了标注,整个捧腹网的数据大体也就这三部分:段子、静态图、动态图。其中,每个list-item中的数据包括:用户头像、用户昵称、笑话的标题、笑话内容(段子内容、静态图、动态图),标签。
“捧腹网”数据列表请求URL分析
最新笑话列表:http://m.pengfu.com/index_num.html, 其中num为第几页。
捧腹段子列表:http://m.pengfu.com/xiaohua_num.html , 其中num为第几页。
趣图列表:http://m.pengfu.com/qutu_num.html , 其中num为第几页。
神回复列表:http://m.pengfu.com/shen_num.html , 其中num为第几页。
使用Jsoup解析网页
Jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
关于如何使用Jsoup并不是本章重点,它并不难使用,具体可以参考jsoup开发指南http://www.open-open.com/jsoup/ ,相信你浏览一遍就知道它的使用方式了。
下面,我们通过Jsoup解析上图网页中的数据list-item 。
首先,我们需要首先获取网页源代码,jsoup提供了一个相当简单的方法,可以直接获取网页源代码,并把它转为Document对象。
Document doc = Jsoup.connect(“http://m.pengfu.com/index_1.html“).get();
当然,你也可以自己通过httpurlconnection获取到网页的数据流,然后通过 Document doc = Jsoup.parse(result);方法把它转为Document对象。
在实际开发中,我们需要用过异步任务,获取、解析网络数据,所以,在这里,我通过httpurlconnection来获取网页源码。
1.封装HTTP请求工具类
package com.lnyp.joke.http;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* Http请求的工具类
*
*/
public class HttpUtils {
private static final int TIMEOUT_IN_MILLIONS = 10000;
public interface CallBack {
void onRequestComplete(String result);
}
/**
* 异步的Get请求
*
* @param urlStr
* @param callBack
*/
public static void doGetAsyn(final String urlStr, final CallBack callBack) {
new Thread() {
public void run() {
try {
String result = doGet(urlStr);
if (callBack != null) {
callBack.onRequestComplete(result);
}
} catch (Exception e) {
e.printStackTrace();
}
}
;
}.start();
}
/**
* Get请求,获得返回数据
*
* @param urlStr
* @return
* @throws Exception
*/
public static String doGet(String urlStr) {
URL url = null;
HttpURLConnection conn = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
try {
url = new URL(urlStr);
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(TIMEOUT_IN_MILLIONS);
conn.setConnectTimeout(TIMEOUT_IN_MILLIONS);
conn.setRequestMethod("GET");
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("User-Agent", "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52");
if (conn.getResponseCode() == 200) {
is = conn.getInputStream();
baos = new ByteArrayOutputStream();
int len = -1;
byte[] buf = new byte[128];
while ((len = is.read(buf)) != -1) {
baos.write(buf, 0, len);
}
baos.flush();
// System.out.print("str : " + baos.toString());
return baos.toString();
} else {
throw new RuntimeException(" responseCode is not 200 ... ");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (is != null)
is.close();
} catch (IOException e) {
}
try {
if (baos != null)
baos.close();
} catch (IOException e) {
}
conn.disconnect();
}
return null;
}
}
2.查询网页源码,转化为Document对象。
private void qryJokes() {
final String url = "http://m.pengfu.com/index_1.html";
System.out.println(url);
HttpUtils.doGetAsyn(url, new HttpUtils.CallBack() {
@Override
public void onRequestComplete(String result) {
if (result == null) {
return;
}
Document doc = Jsoup.parse(result);
}
});
}
3.通过Jsoup解析网页源码,封装列表数据
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.util.ArrayList;
import java.util.List;
/**
* 笑话工具类
*/
public class JokeUtil {
public List<JokeBean> getNewJokelist(Document doc) {
//class等于list-item的div标签
Elements list_item_elements = doc.select("div.list-item");
List<JokeBean> jokeBeanList = new ArrayList<>();
if (list_item_elements.size() > 0) {
for (int i = 0; i < list_item_elements.size(); i++) {
JokeBean jokeBean = new JokeBean();
Element list_item_element = list_item_elements.get(i);
Elements head_name_elements = list_item_element.select("div.head-name");
if (head_name_elements.size() > 0) {
Element head_name_element = head_name_elements.first();
if (head_name_element != null) {
String userAvatar = head_name_element.select("img").first().attr("src");
String userName = head_name_element.select("a[href]").get(1).text(); //带有href属性的a元素
String lastTime = head_name_element.getElementsByClass("dp-i-b").first().text(); //带有href属性的a元素
String shareUrl = head_name_element.select("a[href]").get(1).attr("href");
jokeBean.setUserAvatar(userAvatar);
jokeBean.setUserName(userName);
jokeBean.setLastTime(lastTime);
jokeBean.setShareUrl(shareUrl);
}
}
Element con_img_elements = list_item_element.select("div").get(2);
if (con_img_elements != null) {
if (con_img_elements.select("img") != null) {
Element img_element = con_img_elements.select("img").first();
JokeBean.DataBean dataBean = new JokeBean.DataBean();
if (img_element != null) {
String showImg = img_element.attr("src");
String gifsrcImg = img_element.attr("gifsrc");
String width = img_element.attr("width");
String height = img_element.attr("height");
dataBean.setShowImg(showImg);
dataBean.setGifsrcImg(gifsrcImg);
dataBean.setWidth(width);
dataBean.setHeight(height);
} else {
String content = con_img_elements.text().replaceAll(" ", "\n");
dataBean.setContent(content);
}
jokeBean.setDataBean(dataBean);
}
}
Element tagwrap_clearfix_elements = list_item_element.select("div").get(3);
if (tagwrap_clearfix_elements != null) {
Elements clearfixs = tagwrap_clearfix_elements.select("a[href]"); //带有href属性的a元素
List<String> tags = new ArrayList<>();
for (int j = 0; j < clearfixs.size(); j++) {
String tag = clearfixs.get(j) != null ? clearfixs.get(j).text() : "";
tags.add(tag);
}
jokeBean.setTags(tags);
}
jokeBeanList.add(jokeBean);
}
}
return jokeBeanList;
}
}
本章小结:
本章主要介绍了如何通过解析网页源码获取网页中的数据,其实不难,静下心来,一点点分析,利用jsoup便可以轻而易举的拿到我们想要的数据。
获取到了数据之后,接下我们便可以设计、实现“捧腹”APP。
更多内容,下面会继续详解。
如果你迫不及待的想看源码,请前往https://github.com/zuiwuyuan/Joke查看。谢谢大家的支持。
Android实战:手把手实现“捧腹网”APP(一)-----捧腹网网页分析、数据获取的更多相关文章
- Android实战:手把手实现“捧腹网”APP(三)-----UI实现,逻辑实现
Android实战:手把手实现"捧腹网"APP(一)-–捧腹网网页分析.数据获取 Android实战:手把手实现"捧腹网"APP(二)-–捧腹APP原型设计.实 ...
- Android实战:手把手实现“捧腹网”APP(二)-----捧腹APP原型设计、实现框架选取
Android实战:手把手实现"捧腹网"APP(一)-–捧腹网网页分析.数据获取 Android实战:手把手实现"捧腹网"APP(二)-–捧腹APP原型设计.实 ...
- 项目- Vue全家桶实战去哪网App
最近在学习Vue,花了几天时间跟着做了这个项目,算是对学习Vue入门的一个总结,欢迎同学们star 去哪网APP
- 【Android实战】----从Retrofit源代码分析到Java网络编程以及HTTP权威指南想到的
一.简单介绍 接上一篇[Android实战]----基于Retrofit实现多图片/文件.图文上传中曾说非常想搞明确为什么Retrofit那么屌. 近期也看了一些其源代码分析的文章以及亲自查看了源代码 ...
- [置顶]
【Android实战】----从Retrofit源码分析到Java网络编程以及HTTP权威指南想到的
一.简介 接上一篇[Android实战]----基于Retrofit实现多图片/文件.图文上传中曾说非常想搞明白为什么Retrofit那么屌.最近也看了一些其源码分析的文章以及亲自查看了源码,发现其对 ...
- Android实战简易教程-第三十九枪(第三方短信验证平台Mob和验证码自己主动填入功能结合实例)
用户注冊或者找回password时通常会用到短信验证功能.这里我们使用第三方的短信平台进行验证实例. 我们用到第三方短信验证平台是Mob,地址为:http://mob.com/ 一.注冊用户.获取SD ...
- Android实战简易教程-第四十枪(窃听风云之短信监听)
近期在做监听验证码短信自己主动填入的功能,无意间想到了一个短信监听的办法. 免责声明:短信监听本身是一种违法行为,这里仅仅是技术描写叙述.请大家学习技术就可以.(哈哈) 本实例是基于bmob提供的后台 ...
- 苹果电脑基本设置+Linux 命令+Android 实战集锦
本文微信公众号「AndroidTraveler」首发. 背景 大多数应届毕业生在大学期间使用的比较多的是 windows 电脑,因此初入职场如果拿到一台苹果电脑,可能一时间不能够很快的上手.基于此,这 ...
- 9套Android实战经典项目资料分享给大家
通过项目学习收获更大. 1.基于Android平台实战爱短信项目 下载地址:http://pan.baidu.com/s/1hr8CEry 2.Android平台实战CRM客户关系管理(AChartE ...
随机推荐
- Delphi代码规范
1. 前言 本文档主要是为Delphi开发人员提供一个源代码书写标准,以及程序和文件的命名标准,使他们在编程时有一致格式可遵循.这样,每个编程人员编写的代码能够被其他人理解. 2. 源程序书写规范 2 ...
- java基础之单例模式
单列模式: 单例模式指的是一个类只能有一个实例,这样的类被称为单例类,或者单态类,即Singleton Class 单例类的特点 单例类只可有一个实例 它必须自己创立这唯一的一个实例 它必须给所有其它 ...
- Sql Server实现自动增长
在学习中遇到这个问题 数据库里有编号字段 BH00001 BH00002 BH00003 BH00004 如何实现自动增长 --下面的代码生成长度为8的编号,编号以BH开头,其余6位为流水号. --得 ...
- Linux时间介绍
Linux时钟分为系统时钟(System Clock)和硬件(Real Time Clock,简称RTC)时钟.系统时钟是指当前Linux Kernel中的时钟,而硬件时钟则是主板上由电池供电的时钟, ...
- LeetCode412Fizz Buzz
写一个程序,输出从 1 到 n 数字的字符串表示. 1. 如果 n 是3的倍数,输出"Fizz": 2. 如果 n 是5的倍数,输出"Buzz": 3.如果 n ...
- vue的事件绑定
vue事件有两方面内容:DOM事件 和 自定义事件. DOM事件 vue中采用DOM2级事件的处理方式,为IE9以上的浏览器服务.下面我们先来讲解一下什么是DOM2级事件吧! JS中DOM0级事件有两 ...
- [转]js设计模式—发布订阅模式
发布—订阅模式又叫观察者模式,它定义对象间的一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知.在javascript开发中,一般用事件模型来替代传统的发布—订阅模式.本文将 ...
- python安装和环境变量配置
python环境安装 一.打开官网:http://www.python.org 点击Downloads下载,如下图 python官网 二.根据电脑型号选择下载的版本 下载对应版本号的executabl ...
- 给没有id主键的表添加id,并设置为not null 然后填充自增id
买的ip数据库,表上不带id 使用hibernate比较麻烦,所以直接改表 增加一个字段id,类型int ALTER TABLE t_ip ADD id int; 设置id不为空设置为主键,自增 AL ...
- python基础--类的继承以及mro
继承: 什么是继承: 继承是一种关系,描述两个对象之间什么是什么的关系 在程序中,继承描述的是类和类之间的关系 例如 a继承了b,a就能直接使用b已经存在的方法和属性了 a称之为子类,b称之为父类,成 ...