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 爬虫信息抓取的实例,后续继续补充相关资料,谢谢大家对本站的支持!

(0)

相关推荐

  • java正则表达式简单使用和网页爬虫的制作代码

    正则表达式是一种专门用于对字符串的操作的规则. 1.在String类中就有一些方法是对字符串进行匹配,切割. 判断字符串是否与给出的正则表达式匹配的:boolean matches( String regex); 按照给定的正则表达式对字符串进行切割的:String[]    split(String regex); 将符合正则表达式的字符串替换成我们想要的其他字符串:String  replaceAll(String  regex,String replacement) 2.下面介绍一下正则表

  • java实现网页爬虫的示例讲解

    这一篇目的就是在于网页爬虫的实现,对数据的获取,以便分析. 目录: 1.爬虫原理 2.本地文件数据提取及分析 3.单网页数据的读取 4.运用正则表达式完成超连接的连接匹配和提取 5.广度优先遍历,多网页的数据爬取 6.多线程的网页爬取 7.总结 爬虫实现原理 网络爬虫基本技术处理 网络爬虫是数据采集的一种方法,实际项目开发中,通过爬虫做数据采集一般只有以下几种情况: 1) 搜索引擎 2) 竞品调研 3) 舆情监控 4) 市场分析 网络爬虫的整体执行流程: 1) 确定一个(多个)种子网页 2) 进

  • Java爬虫实战抓取一个网站上的全部链接

    前言:写这篇文章之前,主要是我看了几篇类似的爬虫写法,有的是用的队列来写,感觉不是很直观,还有的只有一个请求然后进行页面解析,根本就没有自动爬起来这也叫爬虫?因此我结合自己的思路写了一下简单的爬虫. 一 算法简介 程序在思路上采用了广度优先算法,对未遍历过的链接逐次发起GET请求,然后对返回来的页面用正则表达式进行解析,取出其中未被发现的新链接,加入集合中,待下一次循环时遍历. 具体实现上使用了Map<String, Boolean>,键值对分别是链接和是否被遍历标志.程序中使用了两个Map集

  • java 爬虫详解及简单实例

    Java爬虫 一.代码 爬虫的实质就是打开网页源代码进行匹配查找,然后获取查找到的结果. 打开网页: URL url = new URL(http://www.cnblogs.com/Renyi-Fan/p/6896901.html); 读取网页内容: BufferedReader bufr = new BufferedReader(new InputStreamReader(url.openStream())); 正则表达式进行匹配: tring mail_regex = "\\w+@\\w+

  • Java爬虫 信息抓取的实现

    今天公司有个需求,需要做一些指定网站查询后的数据的抓取,于是花了点时间写了个demo供演示使用. 思想很简单:就是通过Java访问的链接,然后拿到html字符串,然后就是解析链接等需要的数据.技术上使用Jsoup方便页面的解析,当然Jsoup很方便,也很简单,一行代码就能知道怎么用了: Document doc = Jsoup.connect("http://www.oschina.net/") .data("query", "Java") //

  • Java爬虫实现爬取京东上的手机搜索页面 HttpCliient+Jsoup

    1.需求及配置 需求:爬取京东手机搜索页面的信息,记录各手机的名称,价格,评论数等,形成一个可用于实际分析的数据表格. 使用Maven项目,log4j记录日志,日志仅导出到控制台. Maven依赖如下(pom.xml) <dependencies> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId>

  • Python爬虫实现网页信息抓取功能示例【URL与正则模块】

    本文实例讲述了Python爬虫实现网页信息抓取功能.分享给大家供大家参考,具体如下: 首先实现关于网页解析.读取等操作我们要用到以下几个模块 import urllib import urllib2 import re 我们可以尝试一下用readline方法读某个网站,比如说百度 def test(): f=urllib.urlopen('http://www.baidu.com') while True: firstLine=f.readline() print firstLine 下面我们说

  • Python爬虫实现抓取京东店铺信息及下载图片功能示例

    本文实例讲述了Python爬虫实现抓取京东店铺信息及下载图片功能.分享给大家供大家参考,具体如下: 这个是抓取信息的 from bs4 import BeautifulSoup import requests url = 'https://list.tmall.com/search_product.htm?q=%CB%AE%BA%F8+%C9%D5%CB%AE&type=p&vmarket=&spm=875.7931836%2FA.a2227oh.d100&from=mal

  • Python爬虫实现抓取电影网站信息并入库

    目录 一.环境搭建 1.下载安装包 2.修改环境变量 3.安装依赖模块 二.代码开发 三.运行测试 1.新建电影信息表 2.代码运行 四.问题排查和修复 1.空白字符报错 2.请求报错 一.环境搭建 1.下载安装包 访问 Python官网下载地址:https://www.python.org/downloads/ 下载适合自己系统的安装包: 我用的是 Windows 环境,所以直接下的 exe 包进行安装. 下载后,双击下载包,进入 Python 安装向导,安装非常简单,你只需要使用默认的设置一

  • java简单网页抓取的实现方法

    本文实例讲述了java简单网页抓取的实现方法.分享给大家供大家参考.具体分析如下: 背景介绍 一 tcp简介 1 tcp 实现网络中点对点的传输 2 传输是通过ports和sockets ports提供了不同类型的传输(例如 http的port是80) 1)sockets可以绑定在特定端口上,并且提供传输功能 2)一个port可以连接多个socket 二 URL简介 URL 是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址. 互联网上的每个文件都有一个唯一的

  • Google 爬虫如何抓取 JavaScript 的内容

    我们测试了谷歌爬虫是如何抓取 JavaScript,下面就是我们从中学习到的知识. 认为 Google 不能处理 JavaScript ?再想想吧.Audette Audette 分享了一系列测试结果,他和他同事测试了什么类型的 JavaScript 功能会被 Google 抓取和收录. 长话短说 1. 我们进行了一系列测试,已证实 Google 能以多种方式执行和收录 JavaScript.我们也确认 Google 能渲染整个页面并读取 DOM,由此能收录动态生成的内容. 2. DOM 中的

  • java根据url抓取并生成缩略图的示例

    java根据url抓取并生成缩略图 复制代码 代码如下: public static Bitmap loadImageFromUrl(String url, int sc) {        URL m;        InputStream i = null;        BufferedInputStream bis = null;        ByteArrayOutputStream out = null;        byte isBuffer[] = new byte[1024

  • 零基础写Java知乎爬虫之抓取知乎答案

    前期我们抓取标题是在该链接下: http://www.zhihu.com/explore/recommendations 但是显然这个页面是无法获取答案的. 一个完整问题的页面应该是这样的链接: http://www.zhihu.com/question/22355264 仔细一看,啊哈我们的封装类还需要进一步包装下,至少需要个questionDescription来存储问题描述: import java.util.ArrayList;public class Zhihu { public St

随机推荐