基於Node.js實現一個小小的爬蟲

基於Node.js實現一個小小的爬蟲

之前一直據說有爬蟲這種東西,稍微看了看資料,貌似不是太複雜。javascript

正好了解過node.js,那就基於它來個簡單的爬蟲。css

 

1.本次爬蟲目標:html

從拉鉤招聘網站中找出「前端開發」這一類崗位的信息,並做相應頁面分析,提取出特定的幾個部分如崗位名稱、崗位薪資、崗位所屬公司、崗位發佈日期等。並將抓取到的這些信息,展示出來。前端

 

初始拉鉤網站上界面信息以下:java

 

2.設計方案:node

爬蟲,實際上就是經過相應的技術,抓取頁面上特定的信息。jquery

這裏主要抓取上圖所示崗位列表部分相關的具體崗位信息。ajax

首先,抓取,就得先有地址url:express

http://www.lagou.com/jobs/list_%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91?kd=%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91&spc=1&pl=&gj=&xl=&yx=&gx=&st=&labelWords=label&lc=&workAddress=&city=%E5%85%A8%E5%9B%BD&requestId=&pn=1npm

這個連接就是崗位列表的第一頁的網頁地址。

咱們經過對地址的參數部分進行分析,先無論其餘選擇的參數,只看最後的參數值:pn=1

咱們的目的是經過page來各個抓取,因此設置爲pn = page;

其次,爬蟲要獲取特定信息,就須要特定表明的標識符。

這裏採用分析頁面代碼標籤值、class值、id值來考慮。

經過Firebug對這一小部分審查元素

分析得出將要獲取哪些信息則須要對特定的標識符進行處理。

 

3.代碼編寫:

按照預約的方案,考慮到node.js的使用狀況,經過其內置http模塊進行頁面信息的獲取,另外再經過cheerio.js模塊對DOM的分析,進而轉化爲json格式的數據,控制檯直接輸出或者再次將json數據傳送回瀏覽器端顯示出來。

(cheerio.js這東西的用法很簡單,詳情能夠自行搜索一下。其中最主要的也就下邊這份代碼了,其他的跟jQuery的用法差很少。

就是先將頁面的數據load進來造成一個特定的數據格式,而後經過相似jq的語法,對數據進行解析處理)

複製代碼

var cheerio = require('cheerio'),
    $ = cheerio.load('<h2 class="title">Hello world</h2>');

$('h2.title').text('Hello there!');
$('h2').addClass('welcome');

$.html();
//=> <h2 class="title welcome">Hello there!</h2>

複製代碼

 

採用express模塊化開發,按要求創建好項目後。進入項目目錄,執行npm install安裝所需依賴包。若是還不瞭解express的能夠  到這裏看看

爬蟲須要cheerio.js 因此另外require進來, 因此要另外  npm install cheerio

項目文件不少,爲了簡單處理,就只修改了其中三個文件。(index.ejs  index.js   style.css )

(1)直接修改routes路由中的index.js文件,這也是最核心的部分。

仍是看代碼吧,有足夠的註釋

複製代碼

1 var express = require('express');
 2 var router = express.Router();
 3 var http = require('http');
 4 var cheerio = require('cheerio');
 5 
 6 /* GET home page. */
 7 router.get('/', function(req, res, next) {
 8   res.render('index', { title: '簡單nodejs爬蟲' });
 9   });
10 router.get('/getJobs', function(req, res, next) { // 瀏覽器端發來get請求
11 var page = req.param('page');  //獲取get請求中的參數 page
12 console.log("page: "+page);
13 var Res = res;  //保存,防止下邊的修改
14 //url 獲取信息的頁面部分地址
15 var url = 'http://www.lagou.com/jobs/list_%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91?kd=%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91&spc=1&pl=&gj=&xl=&yx=&gx=&st=&labelWords=label&lc=&workAddress=&city=%E5%85%A8%E5%9B%BD&requestId=&pn=';
16 
17 http.get(url+page,function(res){  //經過get方法獲取對應地址中的頁面信息
18     var chunks = [];
19     var size = 0;
20     res.on('data',function(chunk){   //監聽事件 傳輸
21         chunks.push(chunk);
22         size += chunk.length;
23     });
24     res.on('end',function(){  //數據傳輸完
25         var data = Buffer.concat(chunks,size);  
26         var html = data.toString();
27     //    console.log(html);
28         var $ = cheerio.load(html); //cheerio模塊開始處理 DOM處理
29         var jobs = [];
30 
31         var jobs_list = $(".hot_pos li");
32         $(".hot_pos>li").each(function(){   //對頁面崗位欄信息進行處理  每一個崗位對應一個 li  ,各標識符到頁面進行分析得出
33             var job = {};
34             job.company = $(this).find(".hot_pos_r div").eq(1).find("a").html(); //公司名
35             job.period = $(this).find(".hot_pos_r span").eq(1).html(); //階段
36             job.scale = $(this).find(".hot_pos_r span").eq(2).html(); //規模
37 
38             job.name = $(this).find(".hot_pos_l a").attr("title"); //崗位名
39             job.src = $(this).find(".hot_pos_l a").attr("href"); //崗位連接
40             job.city = $(this).find(".hot_pos_l .c9").html(); //崗位所在城市
41             job.salary = $(this).find(".hot_pos_l span").eq(1).html(); //薪資
42             job.exp = $(this).find(".hot_pos_l span").eq(2).html(); //崗位所需經驗
43             job.time = $(this).find(".hot_pos_l span").eq(5).html(); //發佈時間
44 
45             console.log(job.name);  //控制檯輸出崗位名
46             jobs.push(job);  
47         });
48         Res.json({  //返回json格式數據給瀏覽器端
49             jobs:jobs
50         });
51     });
52 });
53 
54 });
55 
56 module.exports = router;

複製代碼

(2)node.js抓取的核心代碼就是上面的部分了。

下一步就是將抓取到的數據展現出來,因此須要另外一個頁面,將views中的index.ejs模板修改一下

複製代碼

1 <!DOCTYPE html>
 2 <html>
 3   <head>
 4     <title><%= title %></title>
 5     <link rel='stylesheet' href='/stylesheets/style.css' />
 6   </head>
 7   <body>
 8     <h3>【nodejs爬蟲】 獲取拉勾網招聘崗位--前端開發</h3>
 9     <p>初始化完成 ...</p>
10     <p><button class="btn" id="btn0" onclick="cheerFetch(1)">點擊開始抓取第一頁</button></p>
11     <div class="container">
12     <!--<div class="jobs"> </div>-->
13     </div>
14     <div class="footer">
15     <p class="fetching">數據抓取中 ... 請稍後</p>
16         <button class="btn" id="btn1" onclick="cheerFetch(--currentPage)">抓取上一頁</button>
17         <button class="btn" id="btn2" onclick="cheerFetch(++currentPage)">抓取下一頁</button>
18     </div>
19     <script type="text/javascript" src="javascripts/jquery.min.js"></script>
20     <script type="text/javascript">
21     function getData(str){   //獲取到的數據有雜亂..須要把前面部分去掉,只須要data(<em>......<em>  data)
22         if(str){
23         return str.slice(str.lastIndexOf(">")+1);
24     }
25 }
26 
27 document.getElementById("btn1").style.visibility = "hidden";
28 document.getElementById("btn2").style.visibility = "hidden";
29 var currentPage = 0;  //page初始0
30 
31 function cheerFetch(_page){  //抓取數據處理函數
32     if(_page == 1){ 
33         currentPage  = 1;      //開始抓取則更改page
34     }
35     $(document).ajaxSend(function(event, xhr, settings) {  //抓取中...
36         $(".fetching").css("display","block");
37     });
38     $(document).ajaxSuccess(function(event, xhr, settings) {  //抓取成功
39         $(".fetching").css("display","none");
40     });
41     $.ajax({   //開始發送ajax請求至路徑 /getJobs  進而做頁面抓取處理
42         data:{page:_page},  //參數 page = _page
43         dataType: "json",
44         type: "get",
45         url: "/getJobs",
46         success: function(data){   //收到返回的json數據
47             console.log(data);
48             var html = "";
49             $(".container").empty();
50             if(data.jobs.length == 0){ 
51                 alert("Error2: 未找到數據..");
52                 return;
53             }
54             for(var i=0;i<data.jobs.length;i++){   //遍歷數據並提取處理
55                 var job = data.jobs[i];
56                 html += "<div class='jobs'><p><span >崗位序號:</span>  "+((i+1)+15*(currentPage-1))+"</p>"+
57                 "<p>崗位名稱:<a href='"+job.src+"'target='_blank'>"+job.name+"</a></p>"+
58                 "<p><span >崗位所在公司:</span>  "+job.company+"</p>"+
59                 "<p><span>公司階段:</span>  "+getData(job.period)+"</p>"+
60                 "<p><span>崗位規模:</span>  "+getData(job.scale)+"</p>"+
61                 "<p><span>崗位所在城市:</span>  "+job.city+"</p>"+
62                 "<p><span>崗位薪資:</span>  "+getData(job.salary)+"</p>"+
63                 "<p><span>崗位最低經驗要求:</span>  "+getData(job.exp)+"</p>"+
64                 "<p><span>崗位發佈時間:</span>  "+getData(job.time)+"</p>"+
65                 "</div>"
66             }
67 
68             $(".container").append(html);  //展示至頁面
69             if(_page == 1){ 
70                 document.getElementById("btn1").style.visibility = "hidden";
71                 document.getElementById("btn2").style.visibility = "visible";
72             }else if(_page > 1){ 
73                 document.getElementById("btn1").style.visibility = "visible";
74                 document.getElementById("btn2").style.visibility = "visible";
75             }
76         },
77         error: function(){ 
78             alert("Error1: 未找到數據..");
79         }
80     });
81 }
82 
83     </script>
84   </body>
85 </html>

複製代碼

(3)固然了,也少不了樣式部分的簡單修改  public文件下的 style.css

複製代碼

body {
  padding: 20px 50px;
  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}
a {
  color: #00B7FF;
  cursor: pointer;
}
.container{position: relative;width: 1100px;overflow: hidden;zoom:1;}
.jobs{margin: 30px; float: left;}
.jobs span{ color: green; font-weight: bold;}
.btn{cursor: pointer;}
.fetching{display: none;color: red;}
.footer{clear: both;}

複製代碼


基本改動的也就這三個文件了。

因此,若是要測試一下的話,能夠新建項目後,直接修改對應的那三個文件。

修改爲功後,就能夠測試一下了。

 

3.測試結果

1) 首先在控制檯中執行 npm start

2) 接下來在瀏覽器輸入http://localhost:3000/開始訪問

3) 點擊開始抓取(這裏每次抓取15條,也就是原網址對應的15條)

...

4) 再抓取下一頁也仍是能夠的~

 

5) 再來看看控制檯的輸出

相關文章
相關標籤/搜索