Java爬虫 信息抓取的实现
今天公司有个需求,需要做一些指定网站查询后的数据的抓取,于是花了点时间写了个demo供演示使用。
思想很简单:就是通过java访问的链接,然后拿到html字符串,然后就是解析链接等需要的数据。技术上使用jsoup方便页面的解析,当然jsoup很方便,也很简单,一行代码就能知道怎么用了:
document doc = jsoup.connect("http://www.oschina.net/") .data("query", "java") // 请求参数 .useragent("i ' m jsoup") // 设置 user-agent .cookie("auth", "token") // 设置 cookie .timeout(3000) // 设置连接超时时间 .post(); // 使用 post 方法访问 url
下面介绍整个实现过程:
1、分析需要解析的页面:
网址:http://www1.sxcredit.gov.cn/public/infocomquery.do?method=publicindexquery
页面:
先在这个页面上做一次查询:观察下请求的url,参数,method等。
这里我们使用chrome内置的开发者工具(快捷键f12),下面是查询的结果:
我们可以看到url,method,以及参数。知道了如何或者查询的url,下面就开始代码了,为了重用与扩展,我定义了几个类:
1、rule.java用于指定查询url,method,params等
package com.zhy.spider.rule; /** * 规则类 * * @author zhy * */ public class rule { /** * 链接 */ private string url; /** * 参数集合 */ private string[] params; /** * 参数对应的值 */ private string[] values; /** * 对返回的html,第一次过滤所用的标签,请先设置type */ private string resulttagname; /** * class / id / selection * 设置resulttagname的类型,默认为id */ private int type = id ; /** *get / post * 请求的类型,默认get */ private int requestmoethod = get ; public final static int get = 0 ; public final static int post = 1 ; public final static int class = 0; public final static int id = 1; public final static int selection = 2; public rule() { } public rule(string url, string[] params, string[] values, string resulttagname, int type, int requestmoethod) { super(); this.url = url; this.params = params; this.values = values; this.resulttagname = resulttagname; this.type = type; this.requestmoethod = requestmoethod; } public string geturl() { return url; } public void seturl(string url) { this.url = url; } public string[] getparams() { return params; } public void setparams(string[] params) { this.params = params; } public string[] getvalues() { return values; } public void setvalues(string[] values) { this.values = values; } public string getresulttagname() { return resulttagname; } public void setresulttagname(string resulttagname) { this.resulttagname = resulttagname; } public int gettype() { return type; } public void settype(int type) { this.type = type; } public int getrequestmoethod() { return requestmoethod; } public void setrequestmoethod(int requestmoethod) { this.requestmoethod = requestmoethod; } }
简单说一下:这个规则类定义了我们查询过程中需要的所有信息,方便我们的扩展,以及代码的重用,我们不可能针对每个需要抓取的网站写一套代码。
2、需要的数据对象,目前只需要链接,linktypedata.java
package com.zhy.spider.bean; public class linktypedata { private int id; /** * 链接的地址 */ private string linkhref; /** * 链接的标题 */ private string linktext; /** * 摘要 */ private string summary; /** * 内容 */ private string content; public int getid() { return id; } public void setid(int id) { this.id = id; } public string getlinkhref() { return linkhref; } public void setlinkhref(string linkhref) { this.linkhref = linkhref; } public string getlinktext() { return linktext; } public void setlinktext(string linktext) { this.linktext = linktext; } public string getsummary() { return summary; } public void setsummary(string summary) { this.summary = summary; } public string getcontent() { return content; } public void setcontent(string content) { this.content = content; } }
3、核心的查询类:extractservice.java
package com.zhy.spider.core; import java.io.ioexception; import java.util.arraylist; import java.util.list; import java.util.map; import javax.swing.plaf.textui; import org.jsoup.connection; import org.jsoup.jsoup; import org.jsoup.nodes.document; import org.jsoup.nodes.element; import org.jsoup.select.elements; import com.zhy.spider.bean.linktypedata; import com.zhy.spider.rule.rule; import com.zhy.spider.rule.ruleexception; import com.zhy.spider.util.textutil; /** * * @author zhy * */ public class extractservice { /** * @param rule * @return */ public static list<linktypedata> extract(rule rule) { // 进行对rule的必要校验 validaterule(rule); list<linktypedata> datas = new arraylist<linktypedata>(); linktypedata data = null; try { /** * 解析rule */ string url = rule.geturl(); string[] params = rule.getparams(); string[] values = rule.getvalues(); string resulttagname = rule.getresulttagname(); int type = rule.gettype(); int requesttype = rule.getrequestmoethod(); connection conn = jsoup.connect(url); // 设置查询参数 if (params != null) { for (int i = 0; i < params.length; i++) { conn.data(params[i], values[i]); } } // 设置请求类型 document doc = null; switch (requesttype) { case rule.get: doc = conn.timeout(100000).get(); break; case rule.post: doc = conn.timeout(100000).post(); break; } //处理返回数据 elements results = new elements(); switch (type) { case rule.class: results = doc.getelementsbyclass(resulttagname); break; case rule.id: element result = doc.getelementbyid(resulttagname); results.add(result); break; case rule.selection: results = doc.select(resulttagname); break; default: //当resulttagname为空时默认去body标签 if (textutil.isempty(resulttagname)) { results = doc.getelementsbytag("body"); } } for (element result : results) { elements links = result.getelementsbytag("a"); for (element link : links) { //必要的筛选 string linkhref = link.attr("href"); string linktext = link.text(); data = new linktypedata(); data.setlinkhref(linkhref); data.setlinktext(linktext); datas.add(data); } } } catch (ioexception e) { e.printstacktrace(); } return datas; } /** * 对传入的参数进行必要的校验 */ private static void validaterule(rule rule) { string url = rule.geturl(); if (textutil.isempty(url)) { throw new ruleexception("url不能为空!"); } if (!url.startswith("http://")) { throw new ruleexception("url的格式不正确!"); } if (rule.getparams() != null && rule.getvalues() != null) { if (rule.getparams().length != rule.getvalues().length) { throw new ruleexception("参数的键值对个数不匹配!"); } } } }
4、里面用了一个异常类:ruleexception.java
package com.zhy.spider.rule; public class ruleexception extends runtimeexception { public ruleexception() { super(); // todo auto-generated constructor stub } public ruleexception(string message, throwable cause) { super(message, cause); // todo auto-generated constructor stub } public ruleexception(string message) { super(message); // todo auto-generated constructor stub } public ruleexception(throwable cause) { super(cause); // todo auto-generated constructor stub } }
5、最后是测试了:这里使用了两个网站进行测试,采用了不同的规则,具体看代码吧
package com.zhy.spider.test; import java.util.list; import com.zhy.spider.bean.linktypedata; import com.zhy.spider.core.extractservice; import com.zhy.spider.rule.rule; public class test { @org.junit.test public void getdatasbyclass() { rule rule = new rule( "http://www1.sxcredit.gov.cn/public/infocomquery.do?method=publicindexquery", new string[] { "query.enterprisename","query.registationnumber" }, new string[] { "兴网","" }, "cont_right", rule.class, rule.post); list<linktypedata> extracts = extractservice.extract(rule); printf(extracts); } @org.junit.test public void getdatasbycssquery() { rule rule = new rule("http://www.11315.com/search", new string[] { "name" }, new string[] { "兴网" }, "div.g-mn div.con-model", rule.selection, rule.get); list<linktypedata> extracts = extractservice.extract(rule); printf(extracts); } public void printf(list<linktypedata> datas) { for (linktypedata data : datas) { system.out.println(data.getlinktext()); system.out.println(data.getlinkhref()); system.out.println("***********************************"); } } }
输出结果:
深圳市网兴科技有限公司 http://14603257.11315.com *********************************** 荆州市兴网公路物资有限公司 http://05155980.11315.com *********************************** 西安市全兴网吧 # *********************************** 子长县新兴网城 # *********************************** 陕西同兴网络信息有限责任公司第三分公司 # *********************************** 西安高兴网络科技有限公司 # *********************************** 陕西同兴网络信息有限责任公司西安分公司 # ***********************************
最后使用一个baidu新闻来测试我们的代码:说明我们的代码是通用的。
/** * 使用百度新闻,只设置url和关键字与返回类型 */ @org.junit.test public void getdatasbycssqueryuserbaidu() { rule rule = new rule("http://news.baidu.com/ns", new string[] { "word" }, new string[] { "支付宝" }, null, -1, rule.get); list<linktypedata> extracts = extractservice.extract(rule); printf(extracts); }
我们只设置了链接、关键字、和请求类型,不设置具体的筛选条件。
结果:有一定的垃圾数据是肯定的,但是需要的数据肯定也抓取出来了。我们可以设置rule.section,以及筛选条件进一步的限制。
按时间排序 /ns?word=支付宝&ie=utf-8&bs=支付宝&sr=0&cl=2&rn=20&tn=news&ct=0&clk=sortbytime *********************************** x javascript:void(0) *********************************** 支付宝将联合多方共建安全基金 首批投入4000万 http://finance.ifeng.com/a/20140409/12081871_0.shtml *********************************** 7条相同新闻 /ns?word=%e6%94%af%e4%bb%98%e5%ae%9d+cont:2465146414%7c697779368%7c3832159921&same=7&cl=1&tn=news&rn=30&fm=sd *********************************** 百度快照 http://cache.baidu.com/c?m=9d78d513d9d437ab4f9e91697d1cc0161d4381132ba7d3020cd0870fd33a541b0120a1ac26510d19879e20345dfe1e4bea876d26605f75a09bbfd91782a6c1352f8a2432721a844a0fd019adc1452fc423875d9dad0ee7cdb168d5f18c&p=c96ec64ad48b2def49bd9b780b64&newp=c4769a4790934ea95ea28e281c4092695912c10e3dd796&user=baidu&fm=sc&query=%d6%a7%b8%b6%b1%a6&qid=a400f3660007a6c5&p1=1 *********************************** openssl漏洞涉及众多网站 支付宝称暂无数据泄露 http://tech.ifeng.com/internet/detail_2014_04/09/35590390_0.shtml *********************************** 26条相同新闻 /ns?word=%e6%94%af%e4%bb%98%e5%ae%9d+cont:3869124100&same=26&cl=1&tn=news&rn=30&fm=sd *********************************** 百度快照 http://cache.baidu.com/c?m=9f65cb4a8c8507ed4fece7631050803743438014678387492ac3933fc239045c1c3aa5ec677e4742ce932b2152f4174bed843670340537b0efca8e57dfb08f29288f2c367117845615a71bb8cb31649b66cf04fdea44a7ecff25e5aac5a0da4323c044757e97f1fb4d7017dd1cf4&p=8b2a970d95df11a05aa4c32013&newp=9e39c64ad4dd50fa40bd9b7c5253d8304503c52251d5ce042acc&user=baidu&fm=sc&query=%d6%a7%b8%b6%b1%a6&qid=a400f3660007a6c5&p1=2 *********************************** 雅虎日本6月起开始支持支付宝付款 http://www.techweb.com.cn/ucweb/news/id/2025843 ***********************************
如果有什么不足,可以指出;如果觉得对你有用,顶一下~~哈哈
以上就是java 爬虫信息抓取的实例,后续继续补充相关资料,谢谢大家对本站的支持!