基于java的网络爬虫框架(实现京东数据的爬取,并将插入数据库)

原文地址http://blog.csdn.net/qy20115549/article/details/52203722

本文为原创博客,仅供技术学习使用。未经允许,禁止将其复制下来上传到百度文库等平台。

目录

网络爬虫框架

写网络爬虫,一个要有一个逻辑顺序。本文主要讲解我自己经常使用的一个顺序,并且本人经常使用这个框架来写一些简单的爬虫,复杂的爬虫,也是在这个基础上添加其他程序。 

首先,我的工程都是使用maven建的,不会使用maven的,请看之前写的网络爬虫基础。使用Spring MVC框架编写过网站的同学,可以看出框架的重要性与逻辑性。在我的网络爬虫框架中,包含的package有db、main、model、parse、util五个文件。

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

model:用来封装对象,比如我要获取京东书籍的ID、书名、价格,则需要在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中。

网络爬虫实例教学

通过上面的框架,我们可以看出写一个网络爬虫,其实很简单(当然有很复杂的网络爬虫哦)。下面,我将带大家写一个基于java爬虫京东图书信息的网络爬虫,只是做讲解使用,供大家学习和参考。

首先,起点是什么?你可能觉得是main方法,其实不然,起点是你要知道你要获取网站中的哪些数据,然后针对要抓取的数据去写model。如下图,我要获取京东上的图书的价格,和图书名,还有图书的id(id是唯一标识,可作为数据表的主键) 

model

用来封装对象,我要抓取一本书的数据包括,书籍的id,书名及价格。ecliplse中生成set、get方法的快捷键是shift+alt+s然后选择生成setter、getter

package model;
/*
 *  合肥工业大学 管理学院 qianyang [email protected]
 */
public class JdModel {
    private String bookID;
    private String bookName;
    private String bookPrice;
    public String getBookID() {
        return bookID;
    }
    public void setBookID(String bookID) {
        this.bookID = bookID;
    }
    public String getBookName() {
        return bookName;
    }
    public void setBookName(String bookName) {
        this.bookName = bookName;
    }
    public String getBookPrice() {
        return bookPrice;
    }
    public void setBookPrice(String bookPrice) {
        this.bookPrice = bookPrice;
    }
}

main

主方法,尽量要求简单,这里我就这样写了。这里面有注释,很好理解。

package 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 db.MYSQLControl;
import model.JdModel;
import util.URLFecter;
/*
 *  合肥工业大学 管理学院 qianyang [email protected]
 */
public class JdongMain {
    //log4j的是使用,不会的请看之前写的文章
    static final Log logger = LogFactory.getLog(JdongMain.class);
    public static void main(String[] args) throws Exception {
        //初始化一个httpclient
        HttpClient client = new DefaultHttpClient();
        //我们要爬取的一个地址,这里可以从数据库中抽取数据,然后利用循环,可以爬取一个URL队列
        String url="http://search.jd.com/Search?keyword=Python&enc=utf-8&book=y&wq=Python&pvid=33xo9lni.p4a1qb";
        //抓取的数据
        List<JdModel> bookdatas=URLFecter.URLParser(client, url);
        //循环输出抓取的数据
        for (JdModel jd:bookdatas) {
            logger.info("bookID:"+jd.getBookID()+"\t"+"bookPrice:"+jd.getBookPrice()+"\t"+"bookName:"+jd.getBookName());
        }
        //将抓取的数据插入数据库
        MYSQLControl.executeInsert(bookdatas);
    }
}

util

util中包含两个文件,URLFecter 与HTTPUtils,其中URLFecter 调用了HTTPUtils类。

package 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 model.JdModel;
import parse.JdParse;
/*
 *  合肥工业大学 管理学院 qianyang [email protected]
 */
public class URLFecter {
    public static List<JdModel> URLParser (HttpClient client, String url) throws Exception {
        //用来接收解析的数据
        List<JdModel> JingdongData = new ArrayList<JdModel>();
        //获取网站响应的html,这里调用了HTTPUtils类
        HttpResponse response = HTTPUtils.getRawHtml(client, url);
        //获取响应状态码
        int StatusCode = response.getStatusLine().getStatusCode();
        //如果状态响应码为200,则获取html实体内容或者json文件
        if(StatusCode == 200){
            String entity = EntityUtils.toString (response.getEntity(),"utf-8");
            JingdongData = JdParse.getData(entity);
            EntityUtils.consume(response.getEntity());
        }else {
            //否则,消耗掉实体
            EntityUtils.consume(response.getEntity());
        }
        return JingdongData;
    }
}

上面程序调用的HTTPUtils这个类,以下是HTTPUtils这个类。

package 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;
/*
 *  合肥工业大学 管理学院 qianyang [email protected]
 */
public abstract 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;
    }

}

parse

parse主要是通过Jsoup来解析html文件。并将解析后的数据,封装在List集合中,将数据通过层层返回到main方法中。

package parse;

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 model.JdModel;
/*
 * author qianyang [email protected]
 * 用于将上面传下来的html解析,获取我们需要的内容
 * 解析方式,采用Jsoup解析,有不明白Jsoup的可以上网搜索API文档
 * Jsoup是一款很简单的html解析器
 */
public class JdParse {
    public static List<JdModel> getData (String html) throws Exception{
        //获取的数据,存放在集合中
        List<JdModel> data = new ArrayList<JdModel>();
        //采用Jsoup解析
        Document doc = Jsoup.parse(html);
        //获取html标签中的内容
        Elements elements=doc.select("ul[class=gl-warp clearfix]").select("li[class=gl-item]");
        for (Element ele:elements) {
            String bookID=ele.attr("data-sku");
            String bookPrice=ele.select("div[class=p-price]").select("strong").select("i").text();
            String bookName=ele.select("div[class=p-name]").select("em").text();
            //创建一个对象,这里可以看出,使用Model的优势,直接进行封装
            JdModel jdModel=new JdModel();
            //对象的值
            jdModel.setBookID(bookID);
            jdModel.setBookName(bookName);
            jdModel.setBookPrice(bookPrice);
            //将每一个对象的值,保存到List集合中
            data.add(jdModel);
        }
        //返回数据
        return data;
    }
}

db

db中包含两个java文件,MyDataSource,MYSQLControl。这两个文件的作用已在前面说明了。

package db;

import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
/*
 *  合肥工业大学 管理学院 qianyang [email protected]
 */
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("112233");                //MySQL的登陆密码
        ds.setUrl(connectURI);
        return ds;
    }
}

下面是MYSQLControl,主要使用QueryRunner方法操作数据库,使用时是batch方法。

package db;
import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource;
import org.apache.commons.dbutils.QueryRunner;

import model.JdModel;
/*
 * author qianyang [email protected]
 * Mysql操作的QueryRunner方法
 * 一个数据库操作类,别的程序直接调用即可
 */
public class MYSQLControl {

    //根据自己的数据库地址修改
    static DataSource ds = MyDataSource.getDataSource("jdbc:mysql://127.0.0.1:3306/moviedata");
    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<JdModel> jingdongdata) throws SQLException {
        /*
         * 定义一个Object数组,行列
         * 3表示列数,根据自己的数据定义这里面的数字
         * params[i][0]等是对数组赋值,这里用到集合的get方法
         *
         */
        Object[][] params = new Object[jingdongdata.size()][3];
        for ( int i=0; i<params.length; i++ ){
            params[i][0] = jingdongdata.get(i).getBookID();
            params[i][1] = jingdongdata.get(i).getBookName();
            params[i][2] = jingdongdata.get(i).getBookPrice();
        }
        qr.batch("insert into jingdongbook (bookID, bookName, bookPrice)"
                + "values (?,?,?)", params);
        System.out.println("执行数据库完毕!"+"成功插入数据:"+jingdongdata.size()+"条");

    }
}

再看main方法

在main方法中有这样一句程序,这便是调用了操作数据库MYSQLControl程序,将抓取的数据插入到数据库中了

MYSQLControl.executeInsert(bookdatas);
  • 1

爬虫效果展示

到此,便完成了这个简单网络爬虫的编程工作,下面来看看程序运行的结果吧。 

数据库中的结果如下: 

有什么不明白的,请发邮件至[email protected] 合肥工业大学管理学院 qianyang

原文地址:https://www.cnblogs.com/111testing/p/8152671.html

时间: 2024-10-11 23:42:08

基于java的网络爬虫框架(实现京东数据的爬取,并将插入数据库)的相关文章

python网络爬虫学习(六)利用Pyspider+Phantomjs爬取淘宝模特图片

本篇博文在编写时参考了http://cuiqingcai.com/2652.html,向作者表示感谢 一.新的问题与工具 平时在淘宝上剁手的时候,总是会看到各种各样的模特.由于自己就读于一所男女比例三比一的工科院校--写代码之余看看美女也是极好的放松方式.但一张一张点右键–另存为又显得太过麻烦而且不切实际,毕竟图片太多了.于是,我开始考虑用万能的python来解决问题. 我们先看看淘女郎页面的URL,https://mm.taobao.com/json/request_top_list.htm?

Python3网络爬虫(七):使用Beautiful Soup爬取小说

转载请注明作者和出处:http://blog.csdn.net/c406495762 运行平台: Windows Python版本: Python3.x IDE: Sublime text3 一.Beautiful Soup简介 简单来说,Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据.官方解释如下: Beautiful Soup提供一些简单的.python式的函数用来处理导航.搜索.修改分析树等功能.它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简

python3网络爬虫(2.1):爬取堆糖美女

额,明明记得昨晚存了草稿箱,一觉醒来没了,那就简写点(其实是具体怎么解释我也不太懂/xk,纯属个人理解,有错误还望指正) 环境: 版本:python3 IDE:pycharm2017.3.3 浏览器:火狐(浏览器建议火狐,Chrome) 爬取网站:堆糖 选堆糖是因为比较好爬取(除了img文件就是xhr文件),别网站的反爬取对我这个水平来说都太心机了 安装配置什么的之前都写过,这里就不提了,直接开始 1.先来浏览一下这个网站,打开堆糖官网,搜索校花,他就会给我们推荐一些图片,当我们滚动到页面底部时

(转)Python网络爬虫实战:世纪佳缘爬取近6万条数据

又是一年双十一了,不知道从什么时候开始,双十一从“光棍节”变成了“双十一购物狂欢节”,最后一个属于单身狗的节日也成功被攻陷,成为了情侣们送礼物秀恩爱的节日. 翻着安静到死寂的聊天列表,我忽然惊醒,不行,我们不能这样下去,光羡慕别人有什么用,我们要行动起来,去找自己的幸福!!! 我也想“谈不分手的恋爱” !!!内牛满面!!! 注册登陆一气呵成~ 筛选条件,嗯...性别女,年龄...18到24岁,身高嘛,无所谓啦,就按默认155-170吧,地区...嗯北京好,北京近一点,照片?那肯定要啊,必须的!!

【Python3网络爬虫开发实战】 分析Ajax爬取今日头条街拍美图

前言本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理.作者:haoxuan10 本节中,我们以今日头条为例来尝试通过分析Ajax请求来抓取网页数据的方法.这次要抓取的目标是今日头条的街拍美图,抓取完成之后,将每组图片分文件夹下载到本地并保存下来. 准备工作在本节开始之前,请确保已经安装好requests库.如果没有安装,可以参考第1章.另外如果你对python的库不是很熟的话,建议先去小编的Python交流.裙 :一久武其而而流

网络爬虫模拟登陆获取数据并解析实战(二)

目录 分析要获取的数据 程序的结构 构建封装数据的model 模拟登陆程序并解析数据 结果展示 分析要获取的数据 下面继续实战,写一个模拟登陆获取汽车之家,用户信息的程序.如果大家对模拟登陆获取数据不太了解,建议看完http://blog.csdn.net/qy20115549/article/details/52249232,我写的这篇含有抓包获取人人网数据的案例程序,研究透之后,再来看这个要轻松很多. 首先,大家打开汽车之家这个网站(http://i.autohome.com.cn/7741

java 网络爬虫框架

java 网络爬虫框架: apache Nutch ,Heritrix等,主要参照开源社区提供的40个开源项目 文章背景: 最近要写个爬虫抓去新浪微博的数据,然后用hadoop存储后,进行分析,就在网上搜取相关资料. 网友推荐使用python来做,但鉴于本人擅长的是java,学习python需要一定的时间成本,还是选择java.一开始想自己从头写,搜到apache httpClient,  后来想着还是用开源成熟的框架来做,目前觉得apache Nutch 和Heritrix是个不错的选择,不过

【java爬虫】---爬虫+基于接口的网络爬虫

爬虫+基于接口的网络爬虫 上一篇讲了[java爬虫]---爬虫+jsoup轻松爬博客,该方式有个很大的局限性,就是你通过jsoup爬虫只适合爬静态网页,所以只能爬当前页面的所有新闻.如果需要爬一个网 站所有信息,就得通过接口,通过改变参数反复调该网站的接口,爬到该网站的所有数据信息. 本博客以爬金色财经新闻信息为对象,去爬取该网站从建站以来发表的所有新闻信息.下面会一步一步讲解.这里重点重点讲思路,最后我会提供完整源码. 第一步:找接口 你要获得该网站所有新闻数据,第一步当然是获得接口,通过接口

Java网络编程和NIO详解9:基于NIO的网络编程框架Netty

Java网络编程和NIO详解9:基于NIO的网络编程框架Netty 转自https://sylvanassun.github.io/2017/11/30/2017-11-30-netty_introduction/ netty是基于NIO实现的异步事件驱动的网络编程框架,学完NIO以后,应该看看netty的实现,netty框架涉及的内容特别多,这里只介绍netty的基本使用和实现原理,更多扩展的内容将在以后推出. 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎