需求 ##

近期基于 Material Design 重构了自己的新闻 App,数据来源是个问题。

有前人分析了知乎日报、凤凰新闻等 API,依据相应的 URL 能够获取新闻的 JSON 数据。为了锻炼写代码能力,笔者打算爬虫新闻页面,自己获取数据构建 API。

效果图

下图是原站点的页面

爬虫获取了数据,展示到 APP 手机端

爬虫思路

Created with Raphaël 2.1.0開始基于Get请求获取URL对于的网页Html利用Jsoup把Html解析为Document利用Dom的getElementsById等方法获取标题、公布时间、内容等依据标题、公布时间、内容构建javabean给APP使用结束

关于 App 的实现过程能够參看这几篇文章,本文主要解说一下怎样爬虫数据。

Jsoup 简单介绍

Jsoup 是一个 Java 的开源HTML解析器,可直接解析某个URL地址、HTML文本内容。

Jsoup主要有以下功能:

- 从一个URL,文件或字符串中解析HTML。

- 使用DOM或CSS选择器来查找、取出数据;

- 对HTML元素、属性、文本进行操作;

- 清除不受信任的HTML (来防止XSS攻击)

爬虫过程

Get 请求获取网页 HTML

新闻网页Html的DOM树例如以下所看到的:

以下这段代码依据指定的 url,用代码获取get 请求返回的 html 源码。

public static String doGet(String urlStr) throws CommonException {

URL url;

String html = "";

try {

url = new URL(urlStr);

HttpURLConnection connection = (HttpURLConnection) url.openConnection();

connection.setRequestMethod("GET");

connection.setConnectTimeout(5000);

connection.setDoInput(true);

connection.setDoOutput(true);

if (connection.getResponseCode() == 200) {

InputStream in = connection.getInputStream();

html = StreamTool.inToStringByByte(in);

} else {

throw new CommonException("新闻服务器返回值不为200");

}

} catch (Exception e) {

e.printStackTrace();

throw new CommonException("get请求失败");

}

return html;

}

InputStream in = connection.getInputStream();将得到输入流转化为字符串是个普遍需求,我们将其抽象出来,写一个工具方法。

public class StreamTool {

public static String inToStringByByte(InputStream in) throws Exception {

ByteArrayOutputStream outStr = new ByteArrayOutputStream();

byte[] buffer = new byte[1024];

int len = 0;

StringBuilder content = new StringBuilder();

while ((len = in.read(buffer)) != -1) {

content.append(new String(buffer, 0, len, "UTF-8"));

}

outStr.close();

return content.toString();

}

}

解析 HTML 获取标题

利用 google 浏览器的审查元素,找出新闻标题对于的html 代码:

关于举办《经典音乐作品赞赏与人文审美》讲座的通知

我们须要从上面的 HTML 中找出id="article_title"的部分,使用 getElementById(String id) 方法

String htmlStr = HttpTool.doGet(urlStr);

// 将获取的网页 HTML 源码转化为 Document

Document doc = Jsoup.parse(htmlStr);

Element articleEle = doc.getElementById("article");

// 标题

Element titleEle = articleEle.getElementById("article_title");

String titleStr = titleEle.text();

获取公布日期、信息来源

相同找出对于的 HTML 代码

2015-05-28

来源:

浏览次数: 477

思路也和上面相似。使用 getElementById(String id) 方法找出id="article_detail"为Element。再利用getElementsByTag获取span 部分。由于一共同拥有3个 ... ,所以返回的是Elements而不是Element。

// article_detail包含了 2016-01-15 来源: 浏览次数:177

Element detailEle = articleEle.getElementById("article_detail");

Elements details = detailEle.getElementsByTag("span");

// 公布时间

String dateStr = details.get(0).text();

// 新闻来源

String sourceStr = details.get(1).text();

解析浏览次数

假设打印出上面的details.get(2).text(),仅仅会得到

浏览次数:

没有浏览次数?为什么呢?

由于浏览次数是JavaScript 渲染出来的。 Jsoup爬虫可能仅仅提取HTML内容,得不到动态渲染出的数据。

解决方法有两种

在爬虫的时候,内置一个浏览器内核,运行js渲染页面后。再抓取。

所以分析JS请求,找到相应数据的请求url

假设你訪问上面的 urlhttp://see.xidian.edu.cn/index.php/news/click/id/7428。会得到以下的结果

document.write(478)

这个478就是我们须要的浏览次数。我们对上面的url做get 请求,得到返回的字符串。利用正则找出当中的数字。

// 訪问这个新闻页面。浏览次数会+1,次数是 JS 渲染的

String jsStr = HttpTool.doGet(COUNT_BASE_URL + currentPage);

int readTimes = Integer.parseInt(jsStr.replaceAll("\\D+", ""));

// 或者使用以下这个正则方法

// String readTimesStr = jsStr.replaceAll("[^0-9]", "");

解析新闻内容

笔者本来是获取新闻内容纯文字的形式,但后来发现 Android 端也能够显示 CSS 格式,所以后来内容保留了 HTML 格式。

Element contentEle = articleEle.getElementById("article_content");

// 新闻主体内容

String contentStr = contentEle.toString();

// 假设用 text()方法。新闻主体内容的 html 标签会丢失

// 为了在 Android 上用 WebView 显示 html,用toString()

// String contentStr = contentEle.text();

解析图片 Url

注意一个网页上大大小小的图片非常多,为了仅仅获取新闻正文中的内容。我们最好首先定位到新闻内容的Element。然后再利用getElementsByTag(“img”)筛选出图片。

Element contentEle = articleEle.getElementById("article_content");

// 新闻主体内容

String contentStr = contentEle.toString();

// 假设用 text()方法,新闻主体内容的 html 标签会丢失

// 为了在 Android 上用 WebView 显示 html,用toString()

// String contentStr = contentEle.text();

Elements images = contentEle.getElementsByTag("img");

String[] imageUrls = new String[images.size()];

for (int i = 0; i < imageUrls.length; i++) {

imageUrls[i] = images.get(i).attr("src");

}

新闻实体类 JavaBean

上面获取了新闻的标题、公布日期、阅读次数、新闻内容等等,我们自然须要构造一个 javabean。把获取的内容封装进实体类中。

public class ArticleItem {

private int index;

private String[] imageUrls;

private String title;

private String publishDate;

private String source;

private int readTimes;

private String body;

public ArticleItem(int index, String[] imageUrls, String title, String publishDate, String source, int readTimes,

String body) {

this.index = index;

this.imageUrls = imageUrls;

this.title = title;

this.publishDate = publishDate;

this.source = source;

this.readTimes = readTimes;

this.body = body;

}

@Override

public String toString() {

return "ArticleItem [index=" + index + ",\n imageUrls=" + Arrays.toString(imageUrls) + ",\n title=" + title

+ ",\n publishDate=" + publishDate + ",\n source=" + source + ",\n readTimes=" + readTimes + ",\n body=" + body

+ "]";

}

}

測试

public static ArticleItem getNewsItem(int currentPage) throws CommonException {

// 依据后缀的数字,拼接新闻 url

String urlStr = ARTICLE_BASE_URL + currentPage + ".html";

String htmlStr = HttpTool.doGet(urlStr);

Document doc = Jsoup.parse(htmlStr);

Element articleEle = doc.getElementById("article");

// 标题

Element titleEle = articleEle.getElementById("article_title");

String titleStr = titleEle.text();

// article_detail包含了 2016-01-15 来源: 浏览次数:177

Element detailEle = articleEle.getElementById("article_detail");

Elements details = detailEle.getElementsByTag("span");

// 公布时间

String dateStr = details.get(0).text();

// 新闻来源

String sourceStr = details.get(1).text();

// 訪问这个新闻页面。浏览次数会+1,次数是 JS 渲染的

String jsStr = HttpTool.doGet(COUNT_BASE_URL + currentPage);

int readTimes = Integer.parseInt(jsStr.replaceAll("\\D+", ""));

// 或者使用以下这个正则方法

// String readTimesStr = jsStr.replaceAll("[^0-9]", "");

Element contentEle = articleEle.getElementById("article_content");

// 新闻主体内容

String contentStr = contentEle.toString();

// 假设用 text()方法,新闻主体内容的 html 标签会丢失

// 为了在 Android 上用 WebView 显示 html。用toString()

// String contentStr = contentEle.text();

Elements images = contentEle.getElementsByTag("img");

String[] imageUrls = new String[images.size()];

for (int i = 0; i < imageUrls.length; i++) {

imageUrls[i] = images.get(i).attr("src");

}

return new ArticleItem(currentPage, imageUrls, titleStr, dateStr, sourceStr, readTimes, contentStr);

}

public static void main(String[] args) throws CommonException {

System.out.println(getNewsItem(7928));

}

输出信息

ArticleItem [index=7928,

imageUrls=[/uploads/image/20160114/20160114225911_34428.png],

title=电院2014级开展“让诚信之花开遍冬日校园”教育活动,

publishDate=2016-01-14,

source=来源: 电影新闻网,

readTimes=200,

body=

西电新闻网讯 (通讯员 丁彤 王朱丹...)

展望

本文解说了怎样实现Jsoup 网络爬虫。假设文章对您有帮助,感谢捐赠。

近期用 Material Design 重构了自己的新闻 App,新闻数据是利用 Jsoup 实现的。

第1版爬虫是在手机端实现的(我承认这设计非常不好,既费流量又添加client负担),后来在新浪云上实现了一个简单的 JSP 。过滤了原网页的图片、一级栏目等,仅仅返回新闻标题、阅读次数、新闻内容等等。

后期的打算是把爬虫这步移到新浪云上,返回格式化的 JSON 数据给client使用。

可能的话,图片使用七牛CDN(Content Delivery Network 内容分发网络)。在云上利用 Mysql 数据库缓存新闻信息。

參考文章

java爬取app_Java实现爬虫给App提供数据(Jsoup 网络爬虫)相关推荐

  1. python爬虫手机app数据库_Python3网络爬虫(十三):王者荣耀那些事!(Fiddler之手机APP爬取)...

    运行平台: Windows Python版本: Python3.x IDE: Sublime text3 1 前言 暑假回家,"小皇帝"般的生活持续了几天,头几天还挺舒服,闲久了顿 ...

  2. 使用BeautifulSoup爬取想要的标签(《python网络爬虫权威指南》笔记)

    使用BeautifulSoup爬取想要的标签 精确爬取标签 BeautifulSoup中的find()和find_all()方法 BeautifulSoup中的对象 兄弟.子.父.后代标签的处理 抓取 ...

  3. python爬虫能爬取微信密码吗_如何利用Python网络爬虫抓取微信好友数量以及微信好友的男女比例...

    今天我们继续focus on微信,不过这次给大家带来的是利用Python网络爬虫抓取微信好友总数量和微信好友男女性别的分布情况.代码实现蛮简单的,具体的教程如下. 相信大家都知道,直接通过网页抓取微信 ...

  4. python爬虫爬取房源_手把手教你用Python网络爬虫爬取新房数据

    项目背景 大家好,我是J哥. 新房数据,对于房地产置业者来说是买房的重要参考依据,对于房地产开发商来说,也是分析竞争对手项目的绝佳途径,对于房地产代理来说,是踩盘前的重要准备. 今天J哥以「惠民之家」 ...

  5. python爬取国家男女比例_如何利用Python网络爬虫抓取微信好友数量以及微信好友的男女比例?...

    这个实现起来很简单,微信专门给python提供了一个接口包itchat,我们可以通过这个接口获取微信好友信息,继而统计好友数量和男女比例,下面我大概介绍一下实现过程及主要代码,实验环境win7+pyt ...

  6. Jsoup:用Java也可以爬虫,怎么使用Java进行爬虫,用Java爬取网页数据,使用Jsoup爬取数据,爬虫举例:京东搜索

    Jsoup:用Java也可以爬虫,怎么使用Java进行爬虫,用Java爬取网页数据,使用Jsoup爬取数据,爬虫举例:京东搜索 一.资源 为什么接下来的代码中要使用el.getElementsByTa ...

  7. java爬虫京东商品,Java爬虫实现爬取京东上的手机搜索页面 HttpCliient+Jsoup

    1.需求及配置 需求:爬取京东手机搜索页面的信息,记录各手机的名称,价格,评论数等,形成一个可用于实际分析的数据表格. 使用maven项目,log4j记录日志,日志仅导出到控制台. maven依赖如下 ...

  8. Python爬虫-爬取手机应用市场中APP下载量

    一.首先是爬取360手机助手应用市场信息,用来爬取360应用市场,App软件信息,现阶段代码只能爬取下载量,如需爬取别的信息,请自行添加代码. 使用方法: 1.在D盘根目录新建.tet文件,命名为Ap ...

  9. 【用Java爬取网页图片——爬虫爬取数据】

    用Java爬取网页图片--爬虫爬取数据 1.在创建项目中导入jsoup 2.创建一个保存下载图片的路径 3.使用URL读取网页路径,jsoup读取网页内容 4.利用属性标签获取图片连接块 5.因为该路 ...

  10. JAVA爬取虎嗅网截图_java爬虫爬取网站使用多线程(虎嗅网站)

    java爬虫爬取网站使用多线程(虎嗅网站) java爬虫爬取网站使用多线程(虎嗅网站) 图解虎嗅爬虫优化方案 pom 如下: org.apache.httpcomponents httpclient ...

最新文章

  1. java列表包含列表_java – 包含另一个列表的列表
  2. PHP zval内存回收机制和refcount_gc和is_ref_gc
  3. python到底是干嘛用的-python到底能做什么
  4. LR菜鸟入门 -- LightRoom安装/预设
  5. mkyaffs2image编译
  6. 页面上显示的带有乱码名称的js文件是怎么回事?
  7. Slide:配置Oracle 10g双向流复制
  8. 与JSP的初次邂逅……
  9. e4a服务器文件,e4a链接网站服务器
  10. leetcode No.2 两数相加
  11. php serialize和json_encode哪个更快_世界 10 大编程语言,Java 不是第一,PHP 才第五...
  12. MATLAB-电力电子技术仿-单向半波整流电路分析
  13. 一款DYI动态桌面壁纸程序
  14. Python暴力破解密码
  15. idea双击打不开的解决方案
  16. (困难)SQL练习25:获取员工其当前的薪水比其manager当前薪水还高的相关信息
  17. 程序员的数学【多元函数微分学】
  18. GB编码,汉字在编译器中数值
  19. 【基础教程】基于Matlab画花式箱体图
  20. python学习——绘制loss、acc学习曲线

热门文章

  1. 【MySQL】简单易学的MySQL安装教程
  2. 如何统计项目代码行数
  3. SQL Server不允许保存更改的解决方法
  4. 医疗保险管理系统设计 Java
  5. Python实战RBF神经网络
  6. 工业控制领域关键技术趋势
  7. openstack 性能测试
  8. Qt之QSS使用与基本语法
  9. nankai 2082: 靶形数独 数独(9*9)求所有解 DLX+精确覆盖
  10. 51单片机实现电子时钟代码