使用java+Jsoup做简单的网络爬虫,爬取网页资源并写入数据库

使用java+Jsoup做简单的网络爬虫,爬取网页资源并写入数据库

文章目录

  • 使用java+Jsoup做简单的网络爬虫,爬取网页资源并写入数据库
      • 目录结构:
      • 程序执行的顺序:
      • 效果展示:
      • Jsoup文档
      • 代码部分:
        • db-MyDataSource
        • db-MYSQLControl
        • main-SpiderMain
        • model-SpiderModel
        • parse-ReCordParse
        • util-HTTPUtils
        • util-URLParser
        • pom文件

由于工作需要,我近期使用java+Jsoup做了一个简单的网络爬虫程序,都说网络爬虫需要用到Python,但是我们大Java也是可以实现的嘛哈哈 (语言没有高低之分,无引战恶意,Python党请放下你们的西瓜刀哈>_<)

闲言少叙,此次的网络爬虫主要想要做的功能是:将一些“档案类”网站上的资源(文字、图片)抓取下来,写入数据库中:

首先,我们来看一下项目的目录结构:

目录结构:

使用java+Jsoup做简单的网络爬虫,爬取网页资源并写入数据库_第1张图片
这里一共有五个包,db、main、model、parse、util。

  • db:主要放的是数据库操作文件,包含MyDataSource【数据库驱动注册、连接数据库的用户名、密码】,MYSQLControl【连接数据库,插入操作、更新操作、建表操作等】。

  • model:用来封装对象。

  • util:主要放的是httpclient的内容,主要作用时将main方法,传过来的url,通过httpclient相关方法,获取需要解析的html文件或者json文件等。

  • parse:这里面存放的是针对util获取的文件,进行解析,一般采用Jsoup解析;若是针对json数据,可采用正则表达式或者fastjson工具进行解析,建议使用fastjson,因其操作简单,快捷。

  • main:程序起点,也是重点,获取数据,执行数据库语句,存放数据。

程序执行的顺序:

首先,main方法,将url传给util获取响应的html文件,然后util将其获得的html文件,传给parse进行解析,获取最终数据,封装在集合中。解析完毕后,数据返回到main,接着main操作db将数据导入到mysql中。

效果展示:

源网页:http://www.jgsgmbwg.com/bwg.php?cid=6&page=1
使用java+Jsoup做简单的网络爬虫,爬取网页资源并写入数据库_第2张图片
结果展示:
使用java+Jsoup做简单的网络爬虫,爬取网页资源并写入数据库_第3张图片使用java+Jsoup做简单的网络爬虫,爬取网页资源并写入数据库_第4张图片使用java+Jsoup做简单的网络爬虫,爬取网页资源并写入数据库_第5张图片

Jsoup文档

使用Jsoup进行网页元素的抓取,详细操作请参考:https://www.jianshu.com/p/fd5caaaa950d

代码部分:

db-MyDataSource

package com.cesgroup.db;

import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
/**
 * @author :lu.kaifang
 * @date :Created in 2019/9/9 11:27
 * @description:用以确定此工程的数据库连接信息
 * @modified By:lu.kaifang
 * @version: 1.0
 */
public class MyDataSource {
    public static DataSource getDataSource(String connectURI){
        BasicDataSource ds = new BasicDataSource();
        //MySQL的jdbc驱动
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUsername("root");              //所要连接的数据库名
        ds.setPassword("root");                //MySQL的登陆密码
        ds.setUrl(connectURI);
        return ds;
    }
}

db-MYSQLControl

package com.cesgroup.db;

import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource;

import com.cesgroup.model.SpiderModel;
import org.apache.commons.dbutils.QueryRunner;

/**
 * @author :lu.kaifang
 * @date :Created in 2019/9/9 11:29
 * @description:使用QueryRunner方法操作数据库,使用时是batch方法
 * @modified By:lu.kaifang
 * @version: 1.0
 */
public class MYSQLControl {
    //根据自己的数据库地址修改
    static DataSource ds = MyDataSource.getDataSource("jdbc:mysql://127.0.0.1:3306/spider");
    static QueryRunner qr = new QueryRunner(ds);
    //第一类方法
    public static void executeUpdate(String sql){
        try {
            qr.update(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //第二类数据库操作方法
    public static void executeInsert(List reCordData) throws SQLException {
        /*
         * 定义一个Object数组,行列
         * 3表示列数,根据自己的数据定义这里面的数字
         * params[i][0]等是对数组赋值,
         *这里用到集合的get方法
         */
        Object[][] params = new Object[reCordData.size()][3];
        for ( int i=0; i

main-SpiderMain

package com.cesgroup.main;

import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import com.cesgroup.db.MYSQLControl;
import com.cesgroup.model.SpiderModel;
import com.cesgroup.util.URLFecter;
/**
 * @author :lu.kaifang
 * @date :Created in 2019/9/9 11:30
 * @description:这是主程序
 * @modified By:lu.kaifang
 * @version: 1.0
 */
public class SpiderMain {
    //log4j的是使用,不会的请看之前写的文章
    static final Log logger = LogFactory.getLog(SpiderMain.class);
    public static void main(String[] args) throws Exception {
        //初始化一个httpclient
        HttpClient client = new DefaultHttpClient();
        //我们要爬取的一个地址,这里可以从数据库中抽取数据,然后利用循环,可以爬取一个URL队列
        String url="http://www.jgsgmbwg.com/bwg.php?cid=6&page=1";
        //抓取的数据
        List reCorddatas=URLFecter.URLParser(client, url);
        //循环输出抓取的数据
        for (SpiderModel re:reCorddatas) {
            logger.info("ReCordName:"+re.getReCordName()+"\t"+"ReCordData:"+re.getReCordData()+"\t"+"ReCordImg:"+re.getReCordImg());
        }
        //将抓取的数据插入数据库
        MYSQLControl.executeInsert(reCorddatas);
    }
}

model-SpiderModel

package com.cesgroup.model;

/**
 * @author :lu.kaifang
 * @date :Created in 2019/9/9 11:30
 * @description:针对京东页面的实体类
 * 用来封装对象
 * @modified By:lu.kaifang
 * @version: 1.0
 */
public class SpiderModel {
    private String reCordName;
    private String reCordData;
    private String reCordImg;

    public String getReCordName() {
        return reCordName;
    }

    public void setReCordName(String reCordName) {
        this.reCordName = reCordName;
    }

    public String getReCordData() {
        return reCordData;
    }

    public void setReCordData(String reCordData) {
        this.reCordData = reCordData;
    }

    public String getReCordImg() {
        return reCordImg;
    }

    public void setReCordImg(String reCordImg) {
        this.reCordImg = reCordImg;
    }
}

parse-ReCordParse

package com.cesgroup.parse;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import com.cesgroup.model.SpiderModel;
/**
 * @author :lu.kaifang
 * @date :Created in 2019/9/9 11:31
 * @description:针对页面的网络爬虫
 * @modified By:lu.kaifang
 * @version: 1.0
 */
public class ReCordParse {
    public static List getData (String html) throws Exception{
        //获取的数据,存放在集合中
        List data = new ArrayList();
        //采用Jsoup解析
//        System.out.println("html是:"+html);
        //定义图片存储路径
        File path = new File("E:/Img");
        if (!path.exists()){
            path.mkdirs();//若不存在则创建这个文件夹
        }
        Document doc = Jsoup.parse(html);
//		如果出现网站需要有登陆验证,则上面的url会变成登陆页面导致抓取失败,因此可以用下面两行代码代替直接写入url
//        String url = "http://www.jgsgmbwg.com/bwg.php";
//        Document doc = Jsoup.connect(url).get();
        //获取html标签中的内容
        Elements elements=doc.select("ul[class=product_list]").select("li");
        for (Element ele:elements) {
            String reCordName=ele.select("p[class=info]").select("span").text();
            String reCordData=ele.select("p[class=info]").select("a").text();
            String reCordImg = ele.select("a[class=img]").select("img").attr("src");
            //下载图片
//            Document document1 = Jsoup.connect("http://www.jgsgmbwg.com/"+bookImg).ignoreContentType(true).userAgent("Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.15)").timeout(5000).get();
            String bookUrl = "http://www.jgsgmbwg.com/"+reCordImg;
            URL url = new URL(bookUrl);
            String filename = ""+System.currentTimeMillis();
            // 获得连接
            URLConnection connection = url.openConnection();
            // 设置10秒的相应时间
            connection.setConnectTimeout(10 * 1000);
            // 获得输入流
            InputStream in = connection.getInputStream();
            // 获得输出流
            BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(path+"/"+filename+".png"));
            // 构建缓冲区
            byte[] buf = new byte[1024];
            int size;
            // 写入到文件
            while (-1 != (size = in.read(buf))) {
                out.write(buf, 0, size);
            }
            out.close();
            in.close();
            //创建一个对象,这里可以看出,使用Model的优势,直接进行封装
            SpiderModel Model=new SpiderModel();
            //对象的值
            Model.setReCordName(reCordName);
            Model.setReCordData(reCordData);
            Model.setReCordImg(reCordImg);
            Model.setReCordImg("e:/Img/"+filename);
            //将每一个对象的值,保存到List集合中
            data.add(Model);
        }
        //返回数据
        return data;
    }
}

util-HTTPUtils

package com.cesgroup.util;

import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.message.BasicHttpResponse;

/**
 * @author :lu.kaifang
 * @date :Created in 2019/9/9 11:32
 * @description:util中包含两个文件,URLFecter 与HTTPUtils,其中URLFecter 调用了HTTPUtils类
 * @modified By:lu.kaifang
 * @version: 1.0
 */
public class HTTPUtils {
    public static HttpResponse getRawHtml(HttpClient client, String personalUrl) {
        //获取响应文件,即html,采用get方法获取响应数据
        HttpGet getMethod = new HttpGet(personalUrl);
        HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,
                HttpStatus.SC_OK, "OK");
        try {
            //执行get方法
            response = client.execute(getMethod);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // getMethod.abort();
        }
        return response;
    }
}

util-URLParser

package com.cesgroup.util;

import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.util.EntityUtils;
import com.cesgroup.model.SpiderModel;
import com.cesgroup.parse.ReCordParse;

/**
 * @author :lu.kaifang
 * @date :Created in 2019/9/9 11:32
 * @description:util中包含两个文件,URLFecter 与HTTPUtils,其中URLFecter 调用了HTTPUtils类
 * @modified By:lu.kaifang
 * @version: 1.0
 */
public class URLFecter {
    public static List URLParser (HttpClient client, String url) throws Exception {
        //用来接收解析的数据
        List JingdongData = new ArrayList();
        //获取网站响应的html,这里调用了HTTPUtils类
        System.out.println("url是:"+url);
        HttpResponse response = HTTPUtils.getRawHtml(client, url);
        //获取响应状态码
        int StatusCode = response.getStatusLine().getStatusCode();
        //如果状态响应码为200,则获取html实体内容或者json文件
        if(StatusCode == 200){
            System.out.println("response.getEntity()"+response.getEntity());
            String entity = EntityUtils.toString (response.getEntity(),"utf-8");
            JingdongData = ReCordParse.getData(entity);
            System.out.println("entity为:"+entity);
            EntityUtils.consume(response.getEntity());
        }else {
            //否则,消耗掉实体
            EntityUtils.consume(response.getEntity());
        }
        return JingdongData;
    }
}

pom文件




  4.0.0

  com.cesgroup.spider
  spider
  1.0-SNAPSHOT
  war

  spider Maven Webapp
  
  http://www.example.com

  
    UTF-8
    1.7
    1.7
  

  
    
      junit
      junit
      4.11
      test
    
    
    
      commons-dbutils
      commons-dbutils
      1.6
    
    
    
      org.apache.commons
      commons-dbcp2
      2.1.1
    
    
    
      org.apache.httpcomponents
      httpcore
      4.4.10
    
    
    
      org.apache.httpcomponents
      httpclient
      4.5.6
    
    
    
      org.jsoup
      jsoup
      1.11.3
    
    
      mysql
      mysql-connector-java
      5.1.25
    
  
  
  
    spider
    
      
        
          maven-clean-plugin
          3.1.0
        
        
        
          maven-resources-plugin
          3.0.2
        
        
          maven-compiler-plugin
          3.8.0
        
        
          maven-surefire-plugin
          2.22.1
        
        
          maven-war-plugin
          3.2.2
        
        
          maven-install-plugin
          2.5.2
        
        
          maven-deploy-plugin
          2.8.2
        
      
    
  

ok,至此,这个简单的爬虫就完成了~用来爬取一些简单的(类似档案网站)网页是没有什么问题的,如果有些网站有防爬取的,就不能用这么low的方法了,不过有防爬取,就一定有防防爬取,所谓道高一尺,魔高一丈!其他的就靠大家自己去找咯!

你可能感兴趣的:(开发技巧)