当你有幸搜索到这篇博客的时候,相比你已经是以为资深的java程序大师。因此我下面所说的内容你都会能看懂,因此简单的东西就不再叙述,如果有不懂的地方,可以加入数据挖掘群咨询(群号:224739996)。
首先我们的项目有MyEclipse8.6创建的maven项目,名称crawlerDemo,如下:
通过指定的URL抓取网页内容
所谓网页抓取,就是把URL地址中指定的网络资源从网络流中读取出来,保存到本地。类似于使用程序模拟IE浏览器的功能,把URL作为HTTP请求的内容发送到服务器端,然后读取服务器端的响应资源。
Java语言是为网络而生的编程语言,它把网络资源看成是一种文件,它对网络资源的访问和对本地文件的访问一样方便。它把请求和响应封装为流。因此我们可以根据相应内容,获得响应流,之后从流中按字节读取数据。例如,java.net.URL类可以对相应的Web服务器发出请求并且获得响应文档。java.net.URL类有一个默认的构造函数,使用URL地址作为参数,构造URL对象:
- URL pageURL = new URL(path);
接着,可以通过获得的URL对象来取得网络流,进而像操作本地文件一样来操作网络资源:
- InputStream stream = pageURL.openStream();
在实际的项目中,网络环境比较复杂,因此,只用java.net包中的API来模拟IE客户端的工作,代码量非常大。需要处理HTTP返回的状态码,设置HTTP代理,处理HTTPS协议等工作。为了便于应用程序的开发,实际开发时常常使用Apache的HTTP客户端开源项目--HttpClient。它完全能够处理HTTP连接中的各种问题,使用起来非常方便。只需在项目中引入HttpClient.jar包,就可以模拟IE来获取网页内容。例如:
package crawlerDemo; import java.io.IOException; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.methods.GetMethod; /** *通过指定的URL抓取网页内容DEMO *数据挖掘群号:224739996 */ public class httpClientDemo { public static void main( String[] args ) { //创建一个客户端,类似于打开一个浏览器 HttpClient httpclient=new HttpClient(); //创建一个get方法,类似于在浏览器地址栏中输入一个地址 GetMethod getMethod=new GetMethod("http://zhengyunfei.iteye.com/blog/2190701");
//回车,获得响应状态码 try { int statusCode=httpclient.executeMethod(getMethod); System.out.println("statusCode="+statusCode); //查看命中情况,可以获得的东西还有很多,比如head、cookies等 System.out.println("response=" + getMethod.getResponseBodyAsString()); } catch (HttpException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ //释放 getMethod.releaseConnection(); } } } 运行上面demo,结果如下:
statusCode=200 2015-3-9 16:05:22 org.apache.commons.httpclient.HttpMethodBase getResponseBody 警告: Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is recommended. response=<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Script-Type" content="text/javascript"> <script type="text/javascript"> function getCookie(c_name) { // Local function for getting a cookie value if (document.cookie.length > 0) { c_start = document.cookie.indexOf(c_name + "="); if (c_start!=-1) { c_start=c_start + c_name.length + 1; c_end=document.cookie.indexOf(";", c_start); if (c_end==-1) c_end = document.cookie.length; return unescape(document.cookie.substring(c_start,c_end)); } } return ""; } function setCookie(c_name, value, expiredays) { // Local function for setting a value of a cookie var exdate = new Date(); exdate.setDate(exdate.getDate()+expiredays); document.cookie = c_name + "=" + escape(value) + ((expiredays==null) ? "" : ";expires=" + exdate.toGMTString()) + ";path=/"; } function getHostUri() { var loc = document.location; return loc.toString(); } setCookie('YPF8827340282Jdskjhfiw_928937459182JAX666', '220.231.3.154', 10); try { location.reload(true); } catch (err1) { try { location.reload(); } catch (err2) { location.href = getHostUri(); } } </script> </head> <body> <noscript>This site requires JavaScript and Cookies to be enabled. Please change your browser settings or upgrade your browser.</noscript> </body> </html>
上面的示例代码是使用HttpClient进行请求与响应的例子。HttpClient httpclient=new HttpClient()表示创建一个客户端,相当于打开浏览器。GetMethod getMethod=new GetMethod("http://www.blablabla.com");使用get方式对http://www.blablabla.com进行请求。int statusCode=httpclient.executeMethod(getMethod); 执行请求,获取响应状态。 getMethod.getResponseBodyAsString()方法能够以字符串方式获取返回的内容。这也是网页抓取所需要的内容。在这个示例中,只是简单地把返回的内容打印出来,而在实际项目中,通常需要把返回的内容写入本地文件并保存。最后还要关闭网络连接,以免造成资源消耗。
这个例子是用get方式来访问Web资源。通常,get请求方式把需要传递给服务器的参数作为URL的一部分传递给服务器。但是,HTTP协议本身对URL字符串长度有所限制。因此不能传递过多的参数给服务器。为了避免这种问题,通常情况下,采用post方法进行HTTP请求,HttpClient包对post方法也有很好的支持。例如:
package crawlerDemo; import java.io.IOException; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.methods.PostMethod; /** *通过指定的URL抓取网页内容DEMO *数据挖掘群号:224739996 */ public class HttpClientPostDemo { public static void main( String[] args ) { //创建一个客户端,类似于打开一个浏览器 HttpClient httpclient=new HttpClient(); //创建一个post方法,类似于在浏览器地址栏中输入一个地址 PostMethod postMethod=new PostMethod("http://www.pestreet.cn/query/article/1/searchResult.html"); //回车,获得响应状态码 try { //使用数组来传递参数 NameValuePair[] postData = new NameValuePair[1]; //设置参数 postData[0] = new NameValuePair("searchKey", "2015"); postMethod.addParameters(postData); int statusCode=httpclient.executeMethod(postMethod); System.out.println("statusCode="+statusCode); //查看命中情况,可以获得的东西还有很多,比如head、cookies等 System.out.println("response=" + postMethod.getResponseBodyAsString()); } catch (HttpException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ //释放 postMethod.releaseConnection(); } } }
运行结果如下:
statusCode=200 2015-3-9 16:48:18 org.apache.commons.httpclient.HttpMethodBase getResponseBody 警告: Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is recommended. response=<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>搜索结果-财富街</title> <meta property="wb:webmaster" content="d9cb9a0148c6ce38" /> <link href="/style/Config.css" rel="stylesheet" /> <link href="/style/Default.css" rel="stylesheet" /> <link href="/scripts/component/select/select.css" rel="stylesheet" /> <script src="/scripts/lib/jquery.min.js" type="text/javascript"></script> <script src="/scripts/lib/jquery.validate.min.js" type="text/javascript"></script> <script src="/scripts/component/fts.js" type="text/javascript"></script> <script src="/scripts/other/Config.js" type="text/javascript"></script> <script src="/scripts/other/Menu.js" type="text/javascript"></script> <script src="/scripts/other/Default.js" type="text/javascript"></script> <script src="/scripts/other/DAds.js" type="text/javascript"></script> <script src="/scripts/other/RightMenu.js" type="text/javascript"></script> <script src="/scripts/component/pagination.js" type="text/javascript"></script> <!--[if lt IE 9]><script src="/scripts/other/html5.js" language="javascript" type="text/javascript"></script><![endif]--> <!--[if lt IE 7]> <script src="/scripts/other/DD_belatedPNG_0.0.8a.js" language="javascript" type="text/javascript"></script> <script> DD_belatedPNG.fix('*'); </script> <![endif]--> <link href="/style/List.css" rel="stylesheet" /> </head> <body> <!-- Top start --> <script src="/scripts/component/select/select.js" type="text/javascript"></script> <script type="text/javascript"> $(document).ready(function () { var datas = [{field : '私募股权', value : 'smgq', selected : true}, {field : '二级市场', value : 'ejsc'}, {field : '文章', value : 'article'}]; $('#searchSelect').select({datas : datas, btn : $('#fs_select_button'), hidden : $('#fs_select_type'), defaultValue : 'article'}); $('#searchKey').keydown(function(e) { var e = e || event, keycode = e.which || e.keyCode; if(keycode == 13) { searchSubmit(); } }); }); function searchSubmit() { var type = $('#fs_select_type').val(); var searchKey = $('#searchKey').val(); var url = '/query/' + type + '/1/searchResult.html?searchKey=' + encodeURI(encodeURI(searchKey)); window.location.href = url; return false; } </script> <div class="header"> <header> <h1><img src="/images/logo/Logo.jpg" alt="财富街" /></h1> <div class="TopSearch"> <div id="searchSelect" class="searchSelect"> <img src="/images/sbtn.png" id="fs_select_button" class="fs_select_button"/> <input type="hidden" id="fs_select_type" name="searchType" value=""/> </div> <input id="searchKey" name="searchKey" type="text" placeholder="Search" value="2015"> <button type="button" id="searchSubmit" style="cursor:pointer" onclick="searchSubmit();"></button> </div> <h6><img src="/images/tel/TopTel.jpg" alt="热线电话:4006547828" /></h6> <div class="ClearBoth"></div> </header> <nav> <ul> <li><a href="/index.html">首页</a></li> <li id="Menu_1"><a href="javascript:void(0)">我要投资</a> <div id="SmallMenu_1" class="SmallMenu"> <dl> <dd><a href="/smgq/1/56.html">私募股权</a></dd> <dd><a href="/sqtz/1/58.html">申请投资</a></dd> </dl> </div> </li> <li id="Menu_2"><a href="javascript:void(0)">我要募资</a> <div id="SmallMenu_2" class="SmallMenu"> <dl> <dd><a href="/sqmz/1/61.html">申请募资</a></dd> </dl> </div> </li> <li id="Menu_3"><a href="javascript:void(0)">动态与资讯</a> <div id="SmallMenu_3" class="SmallMenu"> <dl> <dd><a href="/wzwslt/1/63.html">最新资讯</a></dd> <dd><a href="/wzwslt/1/64.html">行业风云</a></dd> <dd><a href="/wzwslt/1/65.html">政策动态</a></dd> <dd><a href="/wzslt/1/66.html">研究报告</a></dd> <dd><a href="/wzslt/1/67.html">专业排名</a></dd> </dl> </div> </li> <li id="Menu_4"><a href="javascript:void(0)">乐资会</a> <div id="SmallMenu_4" class="SmallMenu"> <dl> <dd><a href="/jshyhd/1/70.html">乐资会简介</a></dd> <dd><a href="/jshyhd/1/71.html">会员权益</a></dd> <dd><a href="/hyhd/1/72.html">会员活动</a></dd> <dd><a href="/downlb/1/73.html">会员下载专区</a></dd> </dl> </div> </li> <li id="Menu_5"><a href="javascript:void(0)">财富街课堂</a> <div id="SmallMenu_5" class="SmallMenu"> <dl> <dd><a href="/wzwslt/1/108.html">私募股权课堂</a></dd> <dd><a href="/wzwslt/1/153.html">二级市场课堂</a></dd> <dd><a href="/wzwslt/1/154.html">更多知识</a></dd> </dl> </div> </li> <li id="Menu_6"><a href="javascript:void(0)">关于我们</a> <div id="SmallMenu_6" class="SmallMenu"> <dl> <dd><a href="/statement/1/75.html">清科集团简介</a></dd> <dd><a href="/statement/1/76.html">财富街简介</a></dd> <dd><a href="/statement/1/77.html">联系我们</a></dd> <dd><a href="/statement/1/176.html">法律声明</a></dd> </dl> </div> </li> </ul> <div class="Login"><a href="/user/userLogin.html">登录</a>|<a href="/user/userRegister.html" class="Reg">注册</a></div> <div class="ClearBoth"></div> </nav> </div> <!-- Top End --> <!-- Main Start --> <div class="location">我要投资 > 搜索结果</div> <section> <div class="detail"> <div class="NewsList NewsListBox" style="background-color:#ffffff;"> <h4>搜索结果:43个</h4> <ul style="padding-top : 10px;"> <li> <h6><a href="/query/article/2015000000043994.html" target="_blank">投资聚焦Focus》总第96期:2015年私募基金七大政策爆点猜想</a></h6> <span>2015-03-09</span> <p>从2014年走来,私募基金已成为资本市场一股重要力量,年初监管层大力推行备案制,在政策的规范下,随着牛市的来临,私募基金规模快速发展。</p> </li> <li> <h6><a href="/query/article/2015000000043983.html" target="_blank">新三板2015投资攻略</a></h6> <span>2015-03-06</span> <p>2015年,随着市场对竞价交易制度和分层管理的呼声渐高,新三板将受到越来越多的投资者关注。从近期官方密集表态来看,新三板竞价交易有望于2015年中推出。214年8月做市商制度出台后,曾大幅提升新三板公司估值。因此市场普遍预期,竞价交易推出后将进一步提升新三板估值。</p> </li> <li> <h6><a href="/query/article/2015000000043980.html" target="_blank">清科快评:总理报告首提“互联网+”,2015互联网金融迎风口机遇</a></h6> <span>2015-03-06</span> <p>监管层已经充分意识到现有的政策法规并不完全适用于互联网金融,为使得其获得一个健康完善的发展环境,2015年政府将创新金融监管,防范和化解金融风险。大力发展普惠金融,让所有市场主体都能享受到金融服务。</p> </li> <li> <h6><a href="/query/article/2015000000043969.html" target="_blank">清科观察:《2015天使投资白皮书》出炉,国家支持"众创空间"将再燃投资热情</a></h6> <span>2015-03-06</span> <p>2014年全国科技企业孵化器数量超过1600家,国家级孵化器达约600家,非国家级超过1000家,在孵企业8万余家,累计孵化企业约6万家。除了推动孵化器的建设以外,“众创空间”概念还包括了各类创客空间以及交流平台的搭建。</p> </li> <li> <h6><a href="/query/article/2015000000043968.html" target="_blank"> 2015年值得关注的10家硬件创业公司</a></h6> <span>2015-03-05</span> <p>过去几年软件初创公司更容易博得人们的关注,如各种各样的社交应用、手机游戏等。随着众筹平台越来越热门,更多硬件初创公司也开始发力。以下的10家公司或许有望凭借优秀的产品在2015年成为业界关注的焦点。</p> </li> <li> <h6><a href="/query/article/2015000000043961.html" target="_blank">2015年两会股市猜想(附历年两会股市行情)</a></h6> <span>2015-03-05</span> <p>一年一度的全国两会即将拉开帷幕,每年的两会都是投资者关注的重点,将释放怎样的全年经济发展脉络,哪些概念、板块将成为热点,两会期间又是否会有一波特色的“两会行情”?</p> </li> <li> <h6><a href="/query/article/2015000000043959.html" target="_blank">2015全球超级富豪排名发布 中国新入榜人数超美国</a></h6> <span>2015-03-05</span> <p>2015年福布斯全球亿万富豪榜近日正式发布,入榜名单上,都是世界范围内个人或家族净资产超过10亿美元的超级富豪。据统计数据显示,今年新增入榜人数为290人,其中71人来自中国,57位来自美国。</p> </li> </ul> <!-- 分页请求处理 --> <input type="hidden" name="pageNo" value="1"/> <input type="hidden" name="pageSize" value="7"/> <div class="PageBox">当前:1/7 <span>1</span> <a href="javascript:void(0);" onclick="turnOverPage(2);">2</a> … <a href="javascript:void(0);" onclick="turnOverPage(6);">6</a> <a href="javascript:void(0);" onclick="turnOverPage(7);">7</a> 共:43 条 </div> <script language="javascript"> function turnOverPage(no){ var url = '/query/article/(no)/searchResult.html?searchKey=2015'; if(url.indexOf('func:') == 0) { var fName = url.replace('func:', ''); window[fName](no); } else { var lh = url.replace(/\(no\)/, no); window.location.href = encodeURI(encodeURI(lh)); } } </script> </div> </div> <aside> <div class="Right_Service"> <h6>“太好了,我有兴趣”</h6> <p class="Con">拨打400电话或网页对话投资顾问,获得1对1专家服务</p> <p class="Btn Border"><img src="/images/button/Right_ZxBtn2.jpg" style="cursor:pointer;" onclick="notic();" alt="投资顾问联系" /> <img src="/images/button/Right_TelBtn2.jpg" alt="拨打400电话" /></p> <p class="Box">加入乐资会微信微博<br />抢注第一手投资机会</p> <p><img src="/images/Right_ewm2.jpg" alt="二维码" /></p> </div> <script type="text/javascript"> function notic() { $.ajax({ url : fts.baseURI + '/notic/send', type : 'POST', timeout : '1000', async : false, dataType : 'json', success : function(responseText) { var result = responseText.result; var isRelation = responseText.relation; var message = responseText.message; if(result) { if(isRelation) { if(confirm("投资顾问已经联系过您,是否需要再次取得投资顾问联系?")) { updateStatus(); } } else { alert(message); } } else { window.location.href = "/user/userLogin.html" } } }); } function updateStatus() { $.ajax({ url : fts.baseURI + '/notic/updateStatus', type : 'POST', timeout : '1000', async : false, dataType : 'json', success : function(response) { var r = response.result; var m = response.message; if(r) { alert(m); } } }); } </script> </aside> <div class="ClearTab"></div> </section> <!-- Main End --> <!-- footer Start --> <div class="footer"> <div class="EndMenu"> <dl> <dt><a href="javascript:void(0);" style="color:#f2f2f2; font-weight:700;">我要投资</a></dt> <dd><a href="/smgq/1/56.html" style="color:#f2f2f2;">私募股权</a></dd> <dd><a href="/sqtz/1/58.html" style="color:#f2f2f2;">申请投资</a></dd> </dl> <dl> <dt><a href="javascript:void(0);" style="color:#f2f2f2; font-weight:700;">我要募资</a></dt> <dd><a href="/sqmz/1/61.html" style="color:#f2f2f2;">申请募资</a></dd> </dl> <dl> <dt><a href="javascript:void(0);" style="color:#f2f2f2; font-weight:700;">动态与资讯</a></dt> <dd><a href="/wzwslt/1/63.html" style="color:#f2f2f2;">最新资讯</a></dd> <dd><a href="/wzwslt/1/64.html" style="color:#f2f2f2;">行业风云</a></dd> <dd><a href="/wzwslt/1/65.html" style="color:#f2f2f2;">政策动态</a></dd> <dd><a href="/wzslt/1/66.html" style="color:#f2f2f2;">研究报告</a></dd> <dd><a href="/wzslt/1/67.html" style="color:#f2f2f2;">专业排名</a></dd> </dl> <dl> <dt><a href="javascript:void(0);" style="color:#f2f2f2; font-weight:700;">乐资会</a></dt> <dd><a href="/jshyhd/1/70.html" style="color:#f2f2f2;">乐资会简介</a></dd> <dd><a href="/jshyhd/1/71.html" style="color:#f2f2f2;">会员权益</a></dd> <dd><a href="/hyhd/1/72.html" style="color:#f2f2f2;">会员活动</a></dd> <dd><a href="/downlb/1/73.html" style="color:#f2f2f2;">会员下载专区</a></dd> </dl> <dl> <dt><a href="javascript:void(0);" style="color:#f2f2f2; font-weight:700;">财富街课堂</a></dt> <dd><a href="/wzwslt/1/108.html" style="color:#f2f2f2;">私募股权课堂</a></dd> <dd><a href="/wzwslt/1/153.html" style="color:#f2f2f2;">二级市场课堂</a></dd> <dd><a href="/wzwslt/1/154.html" style="color:#f2f2f2;">更多知识</a></dd> </dl> <dl> <dt><a href="javascript:void(0);" style="color:#f2f2f2; font-weight:700;">关于我们</a></dt> <dd><a href="/statement/1/75.html" style="color:#f2f2f2;">清科集团简介</a></dd> <dd><a href="/statement/1/76.html" style="color:#f2f2f2;">财富街简介</a></dd> <dd><a href="/statement/1/77.html" style="color:#f2f2f2;">联系我们</a></dd> <dd><a href="/statement/1/176.html" style="color:#f2f2f2;">法律声明</a></dd> </dl> <div class="EndContact"> <p> 北京市朝阳区霄云路26号鹏润大厦A座12层1203室<br /> 联系电话:+86 10 84580476<br />传真:+86 10 84584529 </p> <ul> <li class="wb" onclick="window.open('http://weibo.com/pwmchina')" style="cursor:pointer">新浪微博</li> <li class="wx" onclick="window.open('/75/wx.html')" style="cursor:pointer">微信</li> </ul> <div class="ClearBoth"></div> </div> <div class="ClearTab"></div> </div> <footer> Copyright @ 2012 Tooks All Rights Reserved 京ICP备12000166号<br> 京公网安备11010502026892号 </footer> </div> <div style="display:none;"> <script type="text/javascript"> var _bdhmProtocol = (("https:" == document.location.protocol) ? " https://" : " http://"); document.write(unescape("%3Cscript src='" + _bdhmProtocol + "hm.baidu.com/h.js%3F7f253a0a0746530f430fcca8f1933364' type='text/javascript'%3E%3C/script%3E")); </script> </div> <!-- footer End --> </body> </html>
上面的例子说明了如何使用post方法来访问Web资源。与get方法不同,post方法可以使用NameValuePair来设置参数,因此可以设置"无限"多的参数。而get方法采用把参数写在URL里面的方式,由于URL有长度限制,因此传递参数的长度会有限制。