node.js+mongodb 爬蟲


demo截圖:

本demo爬瓜子二手車北京區的數據 (注:需要略懂 node.js / mongodb 不懂也沒關系 因為我也不懂啊~~~)

之所以選擇爬瓜子二手車網站有兩點:

一、網站無需登錄,少做模擬登錄;

二、數據鏈接沒有加密,直接可以用;

網上很多node.js爬蟲的栗子

但大多是一個頁面的栗子,很少跟數據庫結合的 所以我這個栗子是糖炒的

我的基本思路是這樣的

1、先在mongodb里存所有頁的鏈接地址的集合

2、在根據這些鏈接地址 一個一個的把詳細信息爬下來

第一步在搜索頁找到翻頁的規律

像搜索頁北京區第一頁就是 

https://www.guazi.com/bj/buy/o1/

第二頁

https://www.guazi.com/bj/buy/o2/

規律就是 

https://www.guazi.com/bj/buy/o + number

然后第一頁的時候你就可以知道最多50頁

這樣你就可以循環這些鏈接在把每個頁面的車的詳情鏈接存到mongodb的集合里

第二步讀mongodb的集合找出所有的鏈接 循環鏈接爬詳情頁數據

項目目錄:

 

目錄講解:

reptile.js      //爬所有鏈接的;

carinfo.js     //爬車輛詳情頁;

package.json  //配置文件

package.json:

 1 {
 2   "name": "sell-car",
 3   "version": "1.0.0",
 4   "description": "",
 5   "main": "index.js",
 6   "scripts": {
 7     "test": "echo \"Error: no test specified\" && exit 1"
 8   },
 9   "author": "",
10   "license": "ISC",
11   "devDependencies": {
12     "cheerio": "^0.22.0",
13     "mongoose": "^4.7.1"
14   }
15 }

 reptile.js 存mongodb集合   在cmd執行的 node reptile.js 

 1 'use strict';
 2 var http = require('https');                      //node https 模塊;
 3 var cheerio = require('cheerio');                 //解析html模塊;
 4 var mongoose = require('mongoose');               //操作mongodb數據庫模塊;
 5 mongoose.connect('mongodb://localhost/car');      //鏈接數據庫;
 6 
 7 var num = 0;                                      //當前第幾頁;
 8 var maxNum = 0;                                   //最大頁數;
 9 
10 var url = 'https://www.guazi.com/bj/buy/o';       //瓜子二手車搜索頁北京區;  
11 
12 var PersonSchema = new mongoose.Schema({          //json的結構;
13       address:String   //定義一個屬性name,類型為String
14     });
15 
16 var sellCar = mongoose.model('sell_car', PersonSchema );   //創建model
17 
18 
19 fetchPage(url+1);           //主程序開始運行
20 
21 function fetchPage(x) {     //封裝了一層函數
22     startRequest(x); 
23 }
24 
25 function startRequest(x) {
26     //采用http模塊向服務器發起一次get請求      
27     http.get(x, function (res) {   
28          
29         var html = '';             //用來存儲請求網頁的整個html內容
30         var titles = [];        
31         res.setEncoding('utf-8');  //防止中文亂碼
32         //監聽data事件,每次取一塊數據
33         res.on('data', function (chunk) { 
34 
35             html += chunk;
36 
37         });
38 
39         //監聽end事件,如果整個網頁內容的html都獲取完畢,就執行回調函數
40         res.on('end', function () {
41 
42             var $ = cheerio.load(html);   //采用cheerio模塊解析html
43         
44             var $a_src = $('.imgtype');   //讀取出當前搜索頁每輛車詳情的地址;
45 
46             $a_src.each(function(i,obj){   //循環每地址鏈接存入數據庫;
47 
48                 var _src = $(obj).attr('href');
49                 
50 
51                 var carHref = new sellCar({ address: _src });  //存入mongodb;
52                 carHref.save(function (err) {
53                   if (err) {
54                     console.log(err);
55                   }
56                 });
57 
58              })
59 
60          num++;  //頁碼增加;
61 
62          if( num == 1 ){         //判斷是第一次,給最大頁數賦值;
63             maxNum = $('.pageLink li').eq($('.pageLink li').length-2).find('span').text();
64          }
65 
66          if( num == maxNum ){    //頁數等於最大頁數等值程序;
67            return ; 
68          }
69 
70          fetchPage(url+num);
71          
72        });
73 
74     });
75 }

 

carinfo.js 車輛詳情 在cmd執行 node  carinfo.js 

  1 'use strict';
  2 var http = require('https');                    //node https 模塊;
  3 var cheerio = require('cheerio');               //解析html模塊;
  4 var mongoose = require('mongoose');             //操作mongodb數據庫模塊;    
  5 mongoose.connect('mongodb://localhost/car');    //鏈接數據庫;    
  6 
  7 var readCarPer = new mongoose.Schema({          //json的結構;
  8       address:String   
  9     });
 10 
 11 var PersonSchema = new mongoose.Schema({        //定義json類型;
 12         info:String,                  //車;
 13         money:String,                 //價錢;
 14         phone:String,                 //電話號碼;
 15         time:String,                  //上牌時間;
 16         mileage:String,               //公里數;
 17         gearbox:String,               //變速箱;
 18         emission:String,              //排放標准;
 19         location:String,              //上牌地;
 20         imgs:Array                    //圖片;
 21     });
 22 
 23 var num = 0;
 24 var readCar = mongoose.model('sell_cars',readCarPer);           
 25 var sellCarInfo = mongoose.model('sell_carInfo', PersonSchema );
 26 
 27 var json = null;                      
 28 var url = 'https://www.guazi.com';    //補鏈接前邊的鏈接;
 29 var time = null;                      //間隔時間;
 30 var maxNum = 0;                       
 31 
 32 
 33 readCar.find({},function(err, character){   //查找數據;
 34 
 35     console.log('成功讀取地址');              
 36 
 37     if(err){
 38         console.log(err);
 39     }else{
 40         json = character;               
 41         maxNum = json.length;
 42         
 43         calls();
 44 
 45     }
 46     
 47 })
 48 
 49 
 50 function calls(){
 51    num++;
 52    if( num > maxNum ){      //判斷是否霸區成功;
 53         console.log('數據爬去完成~~~');
 54         return false;
 55    }
 56 
 57    clearTimeout(time);
 58    var lu = json[num].address;
 59 
 60    time = setTimeout(function(){
 61         
 62         fetchPage(url+lu);      //主程序開始運行
 63 
 64    },5000);
 65 
 66 }
 67 
 68 function fetchPage(x) {     //封裝了一層函數
 69     startRequest(x); 
 70 }
 71 
 72 function startRequest(x) {
 73     console.log(x);
 74      //采用http模塊向服務器發起一次get請求    
 75     http.get(x, function (res) {   
 76          
 77         var html = '';        //用來存儲請求網頁的整個html內容
 78         var titles = [];        
 79         res.setEncoding('utf-8'); //防止中文亂碼
 80         //監聽data事件,每次取一塊數據
 81         res.on('data', function (chunk) { 
 82 
 83             html += chunk;
 84 
 85         });
 86 
 87         //監聽end事件,如果整個網頁內容的html都獲取完畢,就執行回調函數
 88         res.on('end', function () {
 89             
 90             var $ = cheerio.load(html); //采用cheerio模塊解析html
 91     
 92             var info = $('.dt-titletype').text()                    //車名;
 93             var money =  $('.numtype').text();                      //錢;
 94             var phone = $('.teltype').eq(0).text();                 //電話
 95             var time = $('.assort li').eq(0).find('b').text();      //上牌時間
 96             var mileage = $('.assort li').eq(1).find('b').text();   //里程數
 97             var gearbox = $('.assort li').eq(2).find('b').text();   //變速箱
 98             var emission = $('.assort li').eq(3).find('b').text();  //排放標准
 99             var location = $('.assort li').eq(4).find('b').text();  //上牌地
100 
101             var $imgs = $('.dt-pictype img');                   
102             var imgs = [];
103 
104             $imgs.each(function(i,obj){                             //圖片循環賦值;
105                 var img_src = $(obj).attr('data-original');
106                 imgs.push(img_src);
107             });
108 
109             var carInfos = new sellCarInfo({      //保存數據;
110                 info:info,                                                    
111                 money:money,
112                 phone:phone,
113                 time:time,
114                 mileage:mileage,
115                 gearbox:gearbox,
116                 emission:emission,
117                 location:location,
118                 imgs:imgs 
119             });
120 
121             carInfos.save(function (err) {
122               if (err) {
123                 console.log(err);
124               } else {
125                 console.log('成功數據!~~~');
126                 calls();
127               }
128             });
129         
130        });
131 
132     });
133

 當時爬數據的截屏:

 

后記:

這里我沒說 mongodb 安裝、啟動、設置存儲地址 是因為 mongodb本身在window和mac其實是不一樣的所以需要你自己在找找別的文章看看怎么配置(注:window跑真的挺蛋疼的。。。。歡迎去感受一下)

這個栗子的第一個條件就是你要現在cmd里跑起來mongodb 要不剩下的都是白瞎

簡單的mongodb的增刪改查看看 菜鳥教程 就行 實在不行用Robomongo圖形界面也行 

說一個小問題

就是我在爬搜索的車輛鏈接的時候 因為下一頁設置的間隔時間比較短 原本2000條的數據最后只爬下來1160,所以爬車輛詳情的時候把間隔調成了5秒 需要注意一下;

如圖:

 

參考資料:

小小石頭的那些事兒  :  http://blog.csdn.net/yezhenxu1992/article/details/50820629

菜鳥教程                :  http://www.runoob.com/mongodb/mongodb-tutorial.html


免責聲明!

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



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