网页爬虫–历史上的今天
上篇博客中我们知道了,调用第三方的API获得我们想要的数据,如果我们要的数据没有现成的API怎么办?那就需要我们去网站上爬数据了。下面就教大家怎么去网页上爬我们需要的数据。
一.使用Java JDK中的工具自己实现HTTP和HTTPS请求
写一个HttpUtils 工具类:
package org.sunming.util;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;
import org.sm.util.data.MyX509TrustManager;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sf.json.JSONObject;
/**
* 2017-8-19
*
* @author sunming
*/
public class HttpUtils {
private static Logger log = LoggerFactory.getLogger(HttpUtils.class);
/**
* 发起https请求并获取结果
*
* @param requestUrl
* 请求地址
* @param requestMethod
* 请求方式(GET、POST)
* @param outputStr
* 提交的数据
* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
*/
public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
JSONObject jsonObject = null;
StringBuffer buffer = new StringBuffer();
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection httpsUrlConn = (HttpsURLConnection) url.openConnection();
httpsUrlConn.setSSLSocketFactory(ssf);
httpsUrlConn.setDoOutput(true);
httpsUrlConn.setDoInput(true);
httpsUrlConn.setUseCaches(false);
// 设置请求方式(GET/POST)
httpsUrlConn.setRequestMethod(requestMethod);
if ("GET".equalsIgnoreCase(requestMethod)) {
httpsUrlConn.connect();
}
// 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpsUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 将返回的输入流转换成字符串
InputStream inputStream = httpsUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpsUrlConn.disconnect();
jsonObject = JSONObject.fromObject(buffer.toString());
} catch (ConnectException ce) {
log.error("Weixin server connection timed out.");
} catch (Exception e) {
log.error("https request error:{}", e);
}
return jsonObject;
}
public static String httpRequest(String requestUrl, String requestMethod, String outputStr) {
StringBuffer buffer = null;
try {
// 建立连接
URL url = new URL(requestUrl);
HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
httpUrlConn.setDoInput(true);
httpUrlConn.setDoInput(true);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod);
if ("GET".equalsIgnoreCase(requestMethod)) {
httpUrlConn.connect();
}
// 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 获取输入流
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
// 读取返回结果
buffer = new StringBuffer();
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 释放资源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
httpUrlConn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
return buffer.toString();
}
}
工具类即支持GET请求,也支持POST请求,只需要掉用请求的时候传入一个请求方式就可以。
其中HTTPS请求涉及到证书的问题,所以我们需要一个证书信任管理器,这个管理器类需要自己定义,只需要实现X509TrustManager接口。
package org.sunming.util;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
public class MyX509TrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
// TODO Auto-generated method stub
}
@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
// TODO Auto-generated method stub
}
@Override
public X509Certificate[] getAcceptedIssuers() {
// TODO Auto-generated method stub
return null;
}
}
二.选择合适的网页爬去数据
对于历史上的今天,我们选择的是http://www.lssdjt.com/。
网页上的数据很多但是我们需要的只是红框里面的数据怎么得到呢?
先获取网页的源代码
String url = "http://www.lssdjt.com/";
String html = HttpUtils.httpRequest(url, "GET", null);
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=7" />
<meta name="keywords"
content="历史上的今天官网,历史上的今天,历史上今天,历史今天,口述历史,历史故事,历史人物,今天是什么日子,历史上的今天发生了什么" />
<meta name="description"
content="历史上的今天官网(唯一指定网址:http://www.LSSDJT.com),充分挖掘历史老照片资源,以口述形式,适当运用音频渲染方式,以时间为线索,梳理历史上每一天所发生的大事件,给当下带来借鉴与感悟。《历史今天》让照片讲述故事,让历史照亮现实,让今天看清方向。查看历史上每天发生的重大事情,增长知识,开拓眼界,提高人文素养。" />
<title>历史上的今天官网</title>
<LINK href="favicon.ico" type="image/x-icon" rel="shortcut icon">
<link href="/i/2014/css/index.css" type="text/css" rel="stylesheet" />
<!--[if lte ie 8]><script>eval(function(ps, w) { var ca=[],c=w._IE_UPG={},i,l,p; for(i=0,l=ps.length;i<l;i++){ p=ps[i]; c['_'+p]=w[p]; ca.push(p+'=_IE_UPG._'+p) } return 'var '+ca.join(',');}('document self top parent alert setInterval clearInterval setTimeout clearTimeout'.split(' '), window));</script><![endif]-->
</head>
<body>
<div class="mini_wrap mb5 clearfix">
<div class="mini w730">
<ul class="l">
<li class="minilogo"><a href="http://www.lssdjt.com/?back"
target="_self">历史今天官网</a></li>
<li><a href="http://www.lssdjt.com/jieri/" target="_blank">节日大全</a></li>
<li><a href="http://www.lssdjt.com/wnl/" target="_blank">万年历</a></li>
<li> </li>
<li>
<!-- Baidu Button BEGIN -->
<div id="bdshare" class="bdshare_t bds_tools get-codes-bdshare">
<span class="bds_more">分享到:</span><a class="bds_qzone"></a><a
class="bds_tsina"></a><a class="bds_tqq"></a><a
class="bds_renren"></a><a class="bds_t163"></a><a
class="shareCount"></a>
</div> <script type="text/javascript" id="bdshare_js"
data="type=tools&uid=6860001"></script> <script
type="text/javascript" id="bdshell_js"></script> <script
type="text/javascript">
document.getElementById("bdshell_js").src = "http://bdimg.share.baidu.com/static/js/shell_v2.js?cdnversion="
+ Math.ceil(new Date() / 3600000)
</script> <!-- Baidu Button END -->
</li>
</ul>
<ul class="r">
<a href="http://www.lssdjt.com/code/else.htm" target="_blank"><font
color="red">chorme插件</font></a>
<li class="setting"><a href="javascript:void(0);"
id="setting-trigger">换肤</a></li>
</ul>
<p id="skin-box" class="clearfix"></p>
</div>
</div>
<div class="w730 clearfix">
<ul class="mb5 clearfix">
<li class="l w210" id="websiteLogo"><a href="/"><img
src="/i/2014/img/logo.gif" alt="把 历史上的今天官网,唯一指定网址:LSSDJT.COM 设为首页"
border="0" /></a></li>
<li class="r" id="top_banner"><img
src="/i/images/banner_top.png" /></li>
</ul>
<ul class="nav mb5 clearfix">
<div class="info">2017年08月19日 丁酉年六月廿八</div>
</ul>
</div>
<div class="w730 mb5 clearfix">
<div class="box">
<p class="img-focus"></p>
<div id="slideshow">
<p class="paging"></p>
<p class="preview"></p>
<div class="current">
<p>
<a href="/d/19910819.htm" target="_blank"><img
src="http://img.lssdjt.com/200905/17/12212853973.jpg"
alt="苏联“八·一九”事件" /></a>
</p>
<span><a href="/d/19910819.htm" target="_blank">1991年8月19日
苏联“八·一九”事件</a></span>
</div>
<div>
<p>
<a href="/d/19150819.htm" target="_blank"><img
src="http://img.lssdjt.com/200905/17/75214420292.jpg"
alt="“好莱坞第一夫人”英格丽·褒曼出生" /></a>
</p>
<span><a href="/d/19150819.htm" target="_blank">1915年8月19日
“好莱坞第一夫人”英格丽·褒曼出生</a></span>
</div>
<div>
<p>
<a href="/d/19460819.htm" target="_blank"><img
src="http://img.lssdjt.com/201010/2/6B14447546.jpg"
alt="美国第42任总统比尔·克林顿出生" /></a>
</p>
<span><a href="/d/19460819.htm" target="_blank">1946年8月19日
美国第42任总统比尔·克林顿出生</a></span>
</div>
<div>
<p>
<a href="/d/19780819.htm" target="_blank"><img
src="http://img.lssdjt.com/201108/19/FE113431639.jpg"
alt="红卫兵组织在历史舞台消失" /></a>
</p>
<span><a href="/d/19780819.htm" target="_blank">1978年8月19日
红卫兵组织在历史舞台消失</a></span>
</div>
<div>
<p>
<a href="/d/18830819.htm" target="_blank"><img
src="http://img.lssdjt.com/201608/22235625394.jpg"
alt="“时尚女王”香奈儿诞生" /></a>
</p>
<span><a href="/d/18830819.htm" target="_blank">1883年8月19日
“时尚女王”香奈儿诞生</a></span>
</div>
<div>
<p>
<a href="/d/1942819.htm" target="_blank"><img
src="http://img.lssdjt.com/200905/17/8D213858943.jpg"
alt="斯大林格勒大会战开始" /></a>
</p>
<span><a href="/d/1942819.htm" target="_blank">1942年8月19日
斯大林格勒大会战开始</a></span>
</div>
</div>
</div>
<div class="box mt5 p5 clearfix">
<ul class="l">
<img src="/i/dot/dd.gif">《历史上的今天》官网,
<font color=red>老牌新址</font>:http://www.LSSDJT.com “拼音首字母”请认准!。
<a rel="nofollow" href="#" target="_self"
onclick="javascript:clect()">收藏到QQ书签</a>
</ul>
<ul class="r">
<a href="/a/about/course.htm" style="color: red;" target="_blank"><img
src="/i/dot/fx.gif">走近官网!</a>
</ul>
</div>
<div class="box mt5 clearfix">
<ul class="p5">
<a href="/d/20170808.htm" title="8·8九寨沟地震" target="_blank"><img
src="/i/dot/dd.gif">2017年8月8日,8·8九寨沟地震。</a>
<a href="/d/20170807.htm" title="郎咸平遭围堵" target="_blank"><img
src="/i/dot/dd.gif">2017年8月7日,郎咸平遭围堵。</a>
<a href="/d/20170731.htm" title="布达佩斯游泳世锦赛落幕" target="_blank"><img
src="/i/dot/dd.gif">2017年7月31日,布达佩斯游泳世锦赛落幕。</a>
<a href="/d/20170730.htm" title="建军90年大阅兵" target="_blank"><img
src="/i/dot/dd.gif">2017年7月30日,建军90年大阅兵。</a>
<a href="/d/2017730.htm" title="委内瑞拉选举引发暴乱" target="_blank"><img
src="/i/dot/dd.gif">2017年7月30日,委内瑞拉选举引发暴乱。</a>
<a href="/d/20170728.htm" title="“租房落户”新规在无锡实施" target="_blank"><img
src="/i/dot/dd.gif">2017年7月28日,无锡发布全国首个“租购同权”新政。</a>
<a href="/d/20170726.htm" title="印度西孟加拉邦大吉岭地区爆发大规模内乱"
target="_blank"><img src="/i/dot/dd.gif">2017年7月26日,印度西孟加拉邦大吉岭地区爆发新的骚乱。</a>
<a href="/d/20170724.htm" title="中国禁贾斯汀演出" target="_blank"><img
src="/i/dot/dd.gif">2017年7月24日,中国拒绝加拿大男歌手贾斯汀·比伯来华演出。</a>
<a href="/d/2017724.htm" title="游泳世锦赛孙杨400自登顶" target="_blank"><img
src="/i/dot/dd.gif">2017年7月24日,游泳世锦赛孙杨400自登顶。</a>
<a href="/d/20170720.htm" title="科学家首次发现双粲重子" target="_blank"><img
src="/i/dot/dd.gif">2017年7月20日,科学家首次发现双粲重子。</a>
<a href="/d/2017720.htm" title="华人科学家发现“天使粒子”" target="_blank"><img
src="/i/dot/dd.gif">20