Java爬虫,信息抓取的实现

转载请注明出处:

今天公司有个需求,需要做一些指定网站查询后的数据的抓取,于是花了点时间写了个demo供演示使用。

思想很简单:就是通过Java访问的链接,然后拿到html字符串,,然后就是解析链接等需要的数据。

技术上使用Jsoup方便页面的解析,当然Jsoup很方便,也很简单,一行代码就能知道怎么用了:

Document doc = Jsoup.connect("") .data("query", "Java") // 请求参数 .userAgent("I ’ m jsoup") // 设置 User-Agent .cookie("auth", "token") // 设置 cookie .timeout(3000)// 设置连接超时时间 .post();// 使用 POST 方法访问 URL 下面介绍整个实现过程:

1、分析需要解析的页面:

网址:?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.javapackage 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.javapackage 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("")){throw new RuleException("url的格式不正确!");}if (rule.getParams() != null && rule.getValues() != null){if (rule.getParams().length != rule.getValues().length){throw new RuleException("参数的键值对个数不匹配!");}}}}4、里面用了一个异常类:RuleException.javapackage 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.Testpublic void getDatasByClass(){Rule rule = new Rule("?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.Testpublic void getDatasByCssQuery(){Rule rule = new Rule("",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("***********************************");}}}输出结果:深圳市网兴科技有限公司***********************************荆州市兴网公路物资有限公司***********************************西安市全兴网吧#***********************************子长县新兴网城#***********************************陕西同兴网络信息有限责任公司第三分公司#***********************************西安高兴网络科技有限公司#***********************************陕西同兴网络信息有限责任公司西安分公司#***********************************最后使用一个Baidu新闻来测试我们的代码:说明我们的代码是通用的。/** * 使用百度新闻,只设置url和关键字与返回类型 */@org.junit.Testpublic void getDatasByCssQueryUserBaidu(){Rule rule = new Rule("",new String[] { "word" }, new String[] { "支付宝" },null, -1, Rule.GET);List<LinkTypeData> extracts = ExtractService.extract(rule);printf(extracts);}我们只设置了链接、关键字、和请求类型,不设置具体的筛选条件。如果困难是堵砖墙,拍拍它说你还不够高。

Java爬虫,信息抓取的实现

相关文章:

你感兴趣的文章:

标签云: