今天做项目的时候遇到这样一个需求,需要在网页上展示今日黄历信息,数据格式如下

  •   公历时间:2016年04月11日 星期一
  •   农历时间:猴年三月初五
  •   天干地支:丙申年 壬辰月 癸亥日
  •   宜:求子 祈福 开光 祭祀 安床
  •   忌:玉堂(黄道)危日,忌出行

  主要包括公历/农历日期,以及忌宜信息的等。但是手里并没有现成的数据可供使用,怎么办呢?

革命前辈曾经说过,没有枪,没有炮,敌(wang)人(luo)给我们造!网络上有很多现成的在线

万年历应用可供使用,虽然没有现成接口,但是我们可以伸出手来,自己去拿。也就是所谓的数据

抓取。

  这里介绍两个使用的工具,httpClient以及jsoup,简介如下:

  HttpClient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。HttpClient已经应用在很多的项目中,比如Apache Jakarta上很著名的另外两个开源项目Cactus和HTMLUnit都使用了HttpClient。

  httpClient使用方法如下:

  1. 创建HttpClient对象。

  2. 创建请求方法的实例,并指定请求URL。

  3. 调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。

  4. 调用HttpResponse相关方法获取相应内容。

  5. 释放连接。

  jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。

  需要更多信息可以参见官网

  httpClient:http://hc.apache.org/httpcomponents-client-5.0.x/index.html

  jsoup:http://jsoup.org/

  

  接下来我们直接上代码,这里我们抓取2345在线万年历的数据 http://tools.2345.com/rili.htm

  首先我们定义一个实体类Almanac来存储黄历数据

  Almanac.java

 package com.likx.picker.util.bean;

 /**
* 万年历工具实体类
*
* @author 溯源blog
* 2016年4月11日
*/
public class Almanac {
private String solar; /* 阳历 e.g.2016年 4月11日 星期一 */
private String lunar; /* 阴历 e.g. 猴年 三月初五*/
private String chineseAra; /* 天干地支纪年法 e.g.丙申年 壬辰月 癸亥日*/
private String should; /* 宜e.g. 求子 祈福 开光 祭祀 安床*/
private String avoid; /* 忌 e.g. 玉堂(黄道)危日,忌出行*/ public String getSolar() {
return solar;
} public void setSolar(String date) {
this.solar = date;
} public String getLunar() {
return lunar;
} public void setLunar(String lunar) {
this.lunar = lunar;
} public String getChineseAra() {
return chineseAra;
} public void setChineseAra(String chineseAra) {
this.chineseAra = chineseAra;
} public String getAvoid() {
return avoid;
} public void setAvoid(String avoid) {
this.avoid = avoid;
} public String getShould() {
return should;
} public void setShould(String should) {
this.should = should;
} public Almanac(String solar, String lunar, String chineseAra, String should,
String avoid) {
this.solar = solar;
this.lunar = lunar;
this.chineseAra = chineseAra;
this.should = should;
this.avoid = avoid;
}
}

  然后是抓取解析的主程序,写程序之前需要在官网下载需要的jar包

  AlmanacUtil.java

package com.likx.picker.util;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date; import org.apache.http.HttpEntity;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
/**
*<STRONG>类描述</STRONG> : 2345万年历信息爬取工具<p>
*
* @version 1.0 <p>
* @author 溯源blog
*
* <STRONG>创建时间</STRONG> : 2016年4月11日 下午14:15:44<p>
* <STRONG>修改历史</STRONG> :<p>
*<pre>
* 修改人 修改时间 修改内容
* --------------- ------------------- -----------------------------------
*</pre>
*/
public class AlmanacUtil { /**
* 单例工具类
*/
private AlmanacUtil() {
}
/**
* 获取万年历信息
* @return
*/
public static Almanac getAlmanac(){
String url="http://tools.2345.com/rili.htm";
String html=pickData(url);
Almanac almanac=analyzeHTMLByString(html);
return almanac;
} /*
* 爬取网页信息
*/
private static String pickData(String url) {
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
HttpGet httpget = new HttpGet(url);
CloseableHttpResponse response = httpclient.execute(httpget);
try {
// 获取响应实体
HttpEntity entity = response.getEntity();
// 打印响应状态
if (entity != null) {
return EntityUtils.toString(entity);
}
} finally {
response.close();
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭连接,释放资源
try {
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
} /*
* 使用jsoup解析网页信息
*/
private static Almanac analyzeHTMLByString(String html){
String solarDate,lunarDate,chineseAra,should,avoid=" ";
Document document = Jsoup.parse(html);
//公历时间
solarDate=getSolarDate();
//农历时间
Element eLunarDate=document.getElementById("info_nong");
lunarDate=eLunarDate.child(0).html().substring(1,3)+eLunarDate.html().substring(11);
//天干地支纪年法
Element eChineseAra=document.getElementById("info_chang");
chineseAra=eChineseAra.text().toString();
//宜
should=getSuggestion(document,"yi");
//忌
avoid=getSuggestion(document,"ji");
Almanac almanac=new Almanac(solarDate,lunarDate,chineseAra,should,avoid);
return almanac;
}
/*
* 获取忌/宜
*/
private static String getSuggestion(Document doc,String id){
Element element=doc.getElementById(id);
Elements elements=element.getElementsByTag("a");
StringBuffer sb=new StringBuffer();
for (Element e : elements) {
sb.append(e.text()+" ");
}
return sb.toString();
} /*
* 获取公历时间,用yyyy年MM月dd日 EEEE格式表示。
* @return yyyy年MM月dd日 EEEE
*/
private static String getSolarDate() {
Calendar calendar = Calendar.getInstance();
Date solarDate = calendar.getTime();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日 EEEE");
return formatter.format(solarDate);
} }

  为了简单明了我把抓取解析抽象成了几个独立的方法,

  其中pickData()方法使用httpClient来抓取数据到一个字符串中(就是在网页上点击查看源代码看到的HTML源码),

analyzeHTMLByString()方法来解析抓取到的字符串,getSuggestion方法把抓取方法类似的宜忌数据抽象到了

一起,另外因为公历时间可以很容易的自己生成就没有在网页上爬取。

  然后下面是一个测试类简单测试下效果:

AlmanacUtilTest.java

package com.likx.picker.util.test;

public class AlmanacUtilTest {

    public static void main(String args[]){
Almanac almanac=AlmanacUtil.getAlmanac();
System.out.println("公历时间:"+almanac.getSolar());
System.out.println("农历时间:"+almanac.getLunar());
System.out.println("天干地支:"+almanac.getChineseAra());
System.out.println("宜:"+almanac.getShould());
System.out.println("忌:"+almanac.getAvoid());
}
}

  运行结果如下:

  集成到实际项目中效果是这样的:

  

  另外最近博客一直没怎么更新,因为最近考虑到技术氛围的原因,离开了对日外包行业,前往

一家互联网公司就职。说一下最近的感受,那就是一个程序员最核心的竞争力不是学会了多少框架,

掌握多少种工具(当然这些对于程序员也不可或缺),而是扎实的基础以及快速学习的能力,比如今天

这个项目,从对httpClient,jsoup工具一无所知到编写出Demo代码总计大概1个多小时,在之前对于

我来说是不可想象的,在技术氛围浓厚的地方快速get技能的感觉,非常好。

  当然本例只是一个非常浅显的小例子,网页上内容也很容易抓取,httpClient及jsoup工具更多强大

的地方没有体现到,比如httpClient不仅可以发送get请求,而且可以发送post请求,提交表单,传送

文件,还比如jsoup最强大的地方在于它支持仿jquery的选择器。本例仅仅使用了最简单的document.getElementById()

匹配元素,实际上jsoup的选择器异常强大,可以说它就是java版的jquery,比如这样:

Elements links = doc.select("a[href]"); // a with href
Elements pngs = doc.select("img[src$=.png]");
// img with src ending .png
Element masthead = doc.select("div.masthead").first();
// div with class=masthead
Elements resultLinks = doc.select("h3.r > a"); // direct a after h3

  另外还有很多强大的功能水平有限就不一一列举了,感兴趣的可以参照官网文档,也欢迎交流指正。新技能get起来!


使用java开源工具httpClient及jsoup抓取解析网页数据的更多相关文章

  1. selenium抓取动态网页数据

    1.selenium抓取动态网页数据基础介绍 1.1 什么是AJAX AJAX(Asynchronouse JavaScript And XML:异步JavaScript和XML)通过在后台与服务器进 ...

  2. 使用Jsoup 抓取页面的数据

    需要使用的是jsoup-1.7.3.jar包   如果需要看文档我下载请借一步到官网:http://jsoup.org/ 这里贴一下我用到的 Java工程的测试代码 package com.javen ...

  3. 抓取HTML网页数据

    (转)htmlparse filter使用 该类并不是一个通用的工具类,需要按自己的要求实现,这里只记录了Htmlparse.jar包的一些用法.仅此而已! 详细看这里:http://gundumw1 ...

  4. Java开源网页抓取工具httpClient以及jsoup

    网上看到不错的Java网页抓取工具和库 先记录一下 使用java开源工具httpClient及jsoup抓取解析网页数据

  5. jsoup抓取网页+具体解说

    jsoup抓取网页+具体解说 Java 程序在解析 HTML 文档时,相信大家都接触过 htmlparser 这个开源项目.我以前在 IBM DW 上发表过两篇关于 htmlparser 的文章.各自 ...

  6. jsoup抓取网页内容

    java项目有时候我们需要别人网页上的数据,怎么办?我们可以借助第三方架包jsou来实现,jsoup的中文文档,那怎么具体的实现呢?那就跟我一步一步来吧 最先肯定是要准备好这个第三方架包啦,下载地址, ...

  7. Jsoup抓取网页数据完成一个简易的Android新闻APP

    前言:作为一个篮球迷,每天必刷NBA新闻.用了那么多新闻APP,就想自己能不能也做个简易的新闻APP.于是便使用Jsoup抓取了虎扑NBA新闻的数据,完成了一个简易的新闻APP.虽然没什么技术含量,但 ...

  8. 对比使用Charles和Fiddler两个工具及利用Charles抓取https数据(App)

    对比使用Charles和Fiddler两个工具及利用Charles抓取https数据(App) 实验目的:对比使用Charles和Fiddler两个工具 实验对象:车易通App,易销通App 实验结果 ...

  9. 【JAVA系列】Google爬虫如何抓取JavaScript的?

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[JAVA系列]Google爬虫如何抓取Java ...

随机推荐

  1. 返回Json数据浏览器带上<pre></pre>标签解决方法

    问题:  当后台获取到前台传来的文件时(例如上传功能, 导入功能), 返回类型为application/json, 这个时候响应到前端的JSON格式的数据格式可能是: <pre style=&q ...

  2. 人脸识别算法准确率最终超过了人类 The Face Recognition Algorithm That Finally Outperforms Humans

    Everybody has had the experience of not recognising someone they know—changes in pose, illumination ...

  3. Data Base sqlServer sa用户登陆失败的解决办法

    sqlserver sa用户登陆失败的解决办法 如下图以此模仿: 1.右键-属性 2.找到安全: 3.勾选如图: 4.sa用户密码重置: 5.服务重启:

  4. 数据仓库的自动ETL研究

    但是,在实施数据集成的过程中,由于不同用户提供的数据可能来自不同的途径,其数据内容.数据格式和数据质量千差万别,有时甚至会遇到数据格式不能转换或数据转换格式后丢失信息等棘手问题,严重阻碍了数据在各部门 ...

  5. C# 字符流打印类

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.W ...

  6. iReport —— A4打印,只占纸张的一半,如何解决

    有没有遇到过这样的情况:用 iReport 生成的 pdf 文件在预览是好像挺好,但打印时却只占了A4 纸的一半(或许有其他情况,反正是不能占满纸张)? 新建报表时,默认的就是A4尺寸. 经过反复试验 ...

  7. java 反编译插件 JD-Eclipse 和 JD-IntelliJ

    去官网 : http://jd.benow.ca/ 找到 JD-Eclipse 和  JD-IntelliJ,下载,前者安在eclipse上,后者安在as上.

  8. mvp(1)简介及它与mvc区别

    注意:它们是软件架构,不是设计模式 左边mvc    右边mvp MVC和MVP的区别? MVP 是从经典的MVC架构演变而来,它们的基本思想有相通的地方:Controller/Presenter负责 ...

  9. VS2015中添加新建项,找不到ado .net entity datamodel的解决方法

    http://stackoverflow.com/questions/23046081/missing-ado-net-entity-data-model-on-visual-studio-2013 ...

  10. (转)FirstResponder 释放问题

    FirstResponder 释放问题 转自:http://www.cnblogs.com/smileEvday/archive/2012/03/18/2405190.html View的FirstR ...