基於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 1563178220@qq.com */ 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 1563178220@qq.com */ 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 1563178220@qq.com */ 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 1563178220@qq.com */ 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 1563178220@qq.com * 用於將上面傳下來的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 1563178220@qq.com */ 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 1563178220@qq.com * 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

爬蟲效果展示

到此,便完成了這個簡單網絡爬蟲的編程工作,下面來看看程序運行的結果吧。 
這里寫圖片描述

數據庫中的結果如下: 
這里寫圖片描述

有什么不明白的,請發郵件至1563178220@qq.com 合肥工業大學管理學院 qianyang


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM