当前位置: 移动技术网 > IT编程>开发语言>Java > Java爬虫 信息抓取的实现

Java爬虫 信息抓取的实现

2019年07月22日  | 移动技术网IT编程  | 我要评论

今天公司有个需求,需要做一些指定网站查询后的数据的抓取,于是花了点时间写了个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 爬虫信息抓取的实例,后续继续补充相关资料,谢谢大家对本站的支持!

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网