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

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

转载               

转自:http://blog.csdn.net/qy20115549/article/details/52203722

1个人总结: 2.使用JAR3 1.jsoup-1.8.3 解析HTML工具 4 2.httpclient-4.3 连接URL工具 5PS6 1.httpclient有3.0版和4.0版本两个完全不同的JAR包, 7 3.0的已经完全停用,所以不要用错JAR包。 8 4.0JAR包是org.apache.http.client.HttpClient 910 3.log4j-1.2.8 日志工具 11 4.dbcp-1.4 连接池工具 12 5.ojdbc14-10.2.0.2.0 oracle数据库连接工具 13 (PS: 14 1.此包会报找不包的错误,大概原因是此包是收费之类的解决版办法 15 http://blog.csdn.net/qq_37307352/article/details/78639409 16 2.DriverClassName("oracle.jdbc.driver.OracleDriver") 17 ) 18.思路 19 1.写main类按实现思路一步步添加需要的类。首先我们要连接URL所以写了URLFecter类的URLParser方法 20 2.在URLParser方法里我们获得服务器返回的HttpResponse后要判断其StatusLine 21 (服务器返回的状态信息,包括你有没有连接成功。)的StatusCode是不是等于20022 如果等于代表你连接URL成功。 23 3.然后我们需要解析HttpResponse找出我们需要的信息,所以我们写了JdParse类getData方法 24 4.在JdParse类里面我们使用jsoup解析,然后解析出的数据我们需要一个实体类来保存信息。 25 因此我们写了JdModel实体类。 26 5.将每个JdModel对象存到LIST里返回。基本就大功告成了,剩下就存到数据库吧。 27 PS:还有一点,该JD页面如果数一数大概有40~50本书,但我们只爬了30本。为什么呢, 28 因为你浏览JD页面的时候,它一开始是生成了30本书,然后你往下拉才会新加载。 29 这个怎么破呢,我不知道,让我学下去才知道哈哈。 30
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

网络爬虫框架

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

首先,我的工程都是使用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

1package model; 2/* 3 * 合肥工业大学 管理学院 qianyang 1563178220@qq.com 4 */ 5public class JdModel { 6 private String bookID; 7 private String bookName; 8 private String bookPrice; 9 public String getBookID() { 10 return bookID; 11 } 12 public void setBookID(String bookID) { 13 this.bookID = bookID; 14 } 15 public String getBookName() { 16 return bookName; 17 } 18 public void setBookName(String bookName) { 19 this.bookName = bookName; 20 } 21 public String getBookPrice() { 22 return bookPrice; 23 } 24 public void setBookPrice(String bookPrice) { 25 this.bookPrice = bookPrice; 26 } 27} 28
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

main

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

1package main; 2import java.util.List; 3import org.apache.commons.logging.Log; 4import org.apache.commons.logging.LogFactory; 5import org.apache.http.client.HttpClient; 6import org.apache.http.impl.client.DefaultHttpClient; 7import db.MYSQLControl; 8import model.JdModel; 9import util.URLFecter; 10/* 11 * 合肥工业大学 管理学院 qianyang 1563178220@qq.com 12 */ 13public class JdongMain { 14 //log4j的是使用,不会的请看之前写的文章 15 static final Log logger = LogFactory.getLog(JdongMain.class); 16 public static void main(String[] args) throws Exception { 17 //初始化一个httpclient 18 HttpClient client = new DefaultHttpClient(); 19 //我们要爬取的一个地址,这里可以从数据库中抽取数据,然后利用循环,可以爬取一个URL队列 20 String url="http://search.jd.com/Search?keyword=Python&enc=utf-8&book=y&wq=Python&pvid=33xo9lni.p4a1qb"; 21 //抓取的数据 22 List<JdModel> bookdatas=URLFecter.URLParser(client, url); 23 //循环输出抓取的数据 24 for (JdModel jd:bookdatas) { 25 logger.info("bookID:"+jd.getBookID()+"\t"+"bookPrice:"+jd.getBookPrice()+"\t"+"bookName:"+jd.getBookName()); 26 } 27 //将抓取的数据插入数据库 28 MYSQLControl.executeInsert(bookdatas); 29 } 30} 31
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

util

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

1package util; 2import java.util.ArrayList; 3import java.util.List; 4import org.apache.http.HttpResponse; 5import org.apache.http.client.HttpClient; 6import org.apache.http.util.EntityUtils; 7import model.JdModel; 8import parse.JdParse; 9/* 10 * 合肥工业大学 管理学院 qianyang 1563178220@qq.com 11 */ 12public class URLFecter { 13 public static List<JdModel> URLParser (HttpClient client, String url) throws Exception { 14 //用来接收解析的数据 15 List<JdModel> JingdongData = new ArrayList<JdModel>(); 16 //获取网站响应的html,这里调用了HTTPUtils类 17 HttpResponse response = HTTPUtils.getRawHtml(client, url); 18 //获取响应状态码 19 int StatusCode = response.getStatusLine().getStatusCode(); 20 //如果状态响应码为200,则获取html实体内容或者json文件 21 if(StatusCode == 200){ 22 String entity = EntityUtils.toString (response.getEntity(),"utf-8"); 23 JingdongData = JdParse.getData(entity); 24 EntityUtils.consume(response.getEntity()); 25 }else { 26 //否则,消耗掉实体 27 EntityUtils.consume(response.getEntity()); 28 } 29 return JingdongData; 30 } 31} 32 33
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

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

1package util; 2 3import java.io.IOException; 4import org.apache.http.HttpResponse; 5import org.apache.http.HttpStatus; 6import org.apache.http.HttpVersion; 7import org.apache.http.client.HttpClient; 8import org.apache.http.client.methods.HttpGet; 9import org.apache.http.message.BasicHttpResponse; 10/* 11 * 合肥工业大学 管理学院 qianyang 1563178220@qq.com 12 */ 13public abstract class HTTPUtils { 14 public static HttpResponse getRawHtml(HttpClient client, String personalUrl) { 15 //获取响应文件,即html,采用get方法获取响应数据 16 HttpGet getMethod = new HttpGet(personalUrl); 17 HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 18 HttpStatus.SC_OK, "OK"); 19 try { 20 //执行get方法 21 response = client.execute(getMethod); 22 } catch (IOException e) { 23 e.printStackTrace(); 24 25 } finally { 26 // getMethod.abort(); 27 } 28 return response; 29 } 30 31} 32 33
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

parse

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

1package parse; 2 3import java.util.ArrayList; 4import java.util.List; 5import org.jsoup.Jsoup; 6import org.jsoup.nodes.Document; 7import org.jsoup.nodes.Element; 8import org.jsoup.select.Elements; 9import model.JdModel; 10/* 11 * author qianyang 1563178220@qq.com 12 * 用于将上面传下来的html解析,获取我们需要的内容 13 * 解析方式,采用Jsoup解析,有不明白Jsoup的可以上网搜索API文档 14 * Jsoup是一款很简单的html解析器 15 */ 16public class JdParse { 17 public static List<JdModel> getData (String html) throws Exception{ 18 //获取的数据,存放在集合中 19 List<JdModel> data = new ArrayList<JdModel>(); 20 //采用Jsoup解析 21 Document doc = Jsoup.parse(html); 22 //获取html标签中的内容 23 Elements elements=doc.select("ul[class=gl-warp clearfix]").select("li[class=gl-item]"); 24 for (Element ele:elements) { 25 String bookID=ele.attr("data-sku"); 26 String bookPrice=ele.select("div[class=p-price]").select("strong").select("i").text(); 27 String bookName=ele.select("div[class=p-name]").select("em").text(); 28 //创建一个对象,这里可以看出,使用Model的优势,直接进行封装 29 JdModel jdModel=new JdModel(); 30 //对象的值 31 jdModel.setBookID(bookID); 32 jdModel.setBookName(bookName); 33 jdModel.setBookPrice(bookPrice); 34 //将每一个对象的值,保存到List集合中 35 data.add(jdModel); 36 } 37 //返回数据 38 return data; 39 } 40} 41
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

db

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

1package db; 2 3import javax.sql.DataSource; 4import org.apache.commons.dbcp2.BasicDataSource; 5/* 6 * 合肥工业大学 管理学院 qianyang 1563178220@qq.com 7 */ 8public class MyDataSource { 9 public static DataSource getDataSource(String connectURI){ 10 BasicDataSource ds = new BasicDataSource(); 11 //MySQL的jdbc驱动 12 ds.setDriverClassName("com.mysql.jdbc.Driver"); 13 ds.setUsername("root"); //所要连接的数据库名 14 ds.setPassword("112233"); //MySQL的登陆密码 15 ds.setUrl(connectURI); 16 return ds; 17 } 18} 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

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

1package db; 2import java.sql.SQLException; 3import java.util.List; 4import javax.sql.DataSource; 5import org.apache.commons.dbutils.QueryRunner; 6 7import model.JdModel; 8/* 9 * author qianyang 1563178220@qq.com 10 * Mysql操作的QueryRunner方法 11 * 一个数据库操作类,别的程序直接调用即可 12 */ 13public class MYSQLControl { 14 15 //根据自己的数据库地址修改 16 static DataSource ds = MyDataSource.getDataSource("jdbc:mysql://127.0.0.1:3306/moviedata"); 17 static QueryRunner qr = new QueryRunner(ds); 18 //第一类方法 19 public static void executeUpdate(String sql){ 20 try { 21 qr.update(sql); 22 } catch (SQLException e) { 23 e.printStackTrace(); 24 } 25 } 26 //第二类数据库操作方法 27 public static void executeInsert(List<JdModel> jingdongdata) throws SQLException { 28 /* 29 * 定义一个Object数组,行列 30 * 3表示列数,根据自己的数据定义这里面的数字 31 * params[i][0]等是对数组赋值,这里用到集合的get方法 32 * 33 */ 34 Object[][] params = new Object[jingdongdata.size()][3]; 35 for ( int i=0; i<params.length; i++ ){ 36 params[i][0] = jingdongdata.get(i).getBookID(); 37 params[i][1] = jingdongdata.get(i).getBookName(); 38 params[i][2] = jingdongdata.get(i).getBookPrice(); 39 } 40 qr.batch("insert into jingdongbook (bookID, bookName, bookPrice)" 41 + "values (?,?,?)", params); 42 System.out.println("执行数据库完毕!"+"成功插入数据:"+jingdongdata.size()+"条"); 43 44 } 45} 46 47
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

再看main方法

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

1MYSQLControl.executeInsert(bookdatas); 2
  • 1

  • 1

爬虫效果展示

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

数据库中的结果如下:

有什么不明白的,请发邮件至1563178220@qq.com  合肥工业大学管理学院  qianyang

代码交流 2021