1. 程式人生 > >Node.js 實現簡易爬蟲

Node.js 實現簡易爬蟲

為什麼選擇利用node來寫爬蟲呢?就是因為cheerio這個庫,全相容jQuery語法,熟悉的話用起來真真是爽

依賴選擇

  • cheerio: Node.js 版的jQuery
  • http:封裝了一個HTPP伺服器和一個簡易的HTTP客戶端
  • iconv-lite:解決爬取gb2312網頁出現亂碼

初步實現

既然是要爬取網站內容,那我們就應該先去看看網站的基本構成
選取的是電影天堂作為目標網站,想要去爬取所有最新電影的下載連結

分析頁面

頁面結構如下:
ygdy.tiff

我們可以看到每個電影的標題都在一個classulinka標籤下,再往上定位,我們可以看到最外部的盒子classco_content8

ok,可以開工了

獲取一頁電影標題

首先引入依賴,並設定需要爬取的url

var cheerio = require('cheerio');var http = require('http');var iconv = require('iconv-lite');var url = 'http://www.ygdy8.net/html/gndy/dyzz/index.html';

核心程式碼 index.js

http.get(url, function(sres) { var chunks = []; sres.on('data', function(chunk) { chunks.push(chunk); }); // chunks裡面儲存著網頁的 html 內容,將它zhuan ma傳給 cheerio.load 之後 // 就可以得到一個實現了 jQuery 介面的變數,將它命名為 `$` // 剩下就都是 jQuery 的內容了 sres.on('end'
, function() { var titles = []; //由於咱們發現此網頁的編碼格式為gb2312,所以需要對其進行轉碼,否則亂碼 //依據:“<meta http-equiv="Content-Type" content="text/html; charset=gb2312">” var html = iconv.decode(Buffer.concat(chunks), 'gb2312'); var $ = cheerio.load(html, {decodeEntities: false}); $('.co_content8 .ulink'
).each(function (idx, element) { var $element = $(element); titles.push({ title: $element.text() }) }) console.log(titles); });});

執行node index

結果如下
node-repfile-title.png

成功獲取電影title,那如果我想獲取多個頁面的title呢,總不可能一個一個url去改吧。這當然有辦法,請往下看!

獲取多頁電影標題

我們只要將之前的程式碼封裝成一個函式並遞迴執行就完成了

核心程式碼 index.js

var index = 1; //頁面數控制var url = 'http://www.ygdy8.net/html/gndy/dyzz/list_23_';var titles = []; //用於儲存titlefunction getTitle(url, i) { console.log("正在獲取第" + i + "頁的內容"); http.get(url + i + '.html', function(sres) { var chunks = []; sres.on('data', function(chunk) { chunks.push(chunk); }); sres.on('end', function() { var html = iconv.decode(Buffer.concat(chunks), 'gb2312'); var $ = cheerio.load(html, {decodeEntities: false}); $('.co_content8 .ulink').each(function (idx, element) { var $element = $(element); titles.push({ title: $element.text() }) }) if(i < 2) { //為了方便只爬了兩頁 getTitle(url, ++index); //遞迴執行,頁數+1 } else { console.log(titles); console.log("Title獲取完畢!"); } }); });}function main() { console.log("開始爬取"); getTitle(url, index);}main(); //執行主函式

結果如下
node-reptitle-many-title.png

獲取電影下載連線

如果是人工操作,我們需要一次操作,通過點選進入電影詳情頁才能找到下載地址
那我們通過node如何來實現呢

常規先來分析頁面佈局
ygdy-des.png

我們如果想要準確定位到下載連結,需要先找到idZoom的div,下載連結就在這個div下的tr下的a標籤內。

那我們就再定義一個函式,用於獲取下載連結

getBtLink()

function getBtLink(urls, n) { //urls裡面包含著所有詳情頁的地址 console.log("正在獲取第" + n + "個url的內容"); http.get('http://www.ygdy8.net' + urls[n].title, function(sres) { var chunks = []; sres.on('data', function(chunk) { chunks.push(chunk); }); sres.on('end', function() { var html = iconv.decode(Buffer.concat(chunks), 'gb2312'); //進行轉碼 var $ = cheerio.load(html, {decodeEntities: false}); $('#Zoom td').children('a').each(function (idx, element) { var $element = $(element); btLink.push({ bt: $element.attr('href') }) }) if(n < urls.length - 1) { getBtLink(urls, ++count); //遞迴 } else { console.log("btlink獲取完畢!"); console.log(btLink); } }); });}

再次執行 node index
WX20170318-190537@2x.png
WX20170318-190549@2x.png

就這樣我們將3個頁面內所有電影的下載連結獲取完畢,是不是很簡單?

儲存資料

我們講這些資料爬取出來當然是要進行儲存的啊,在這裡我選用了MongoDB來對其進行儲存處理

資料儲存函式 save()

function save() { var MongoClient = require('mongodb').MongoClient; //匯入依賴 MongoClient.connect(mongo_url, function (err, db) { if (err) { console.error(err); return; } else { console.log("成功連線資料庫"); var collection = db.collection('node-reptitle'); collection.insertMany(btLink, function (err,result) { //插入資料 if (err) { console.error(err); } else { console.log("儲存資料成功"); } }) db.close(); } });}

這裡的操作很簡單,就沒必要上mongoose啦
再次執行 node index
mongodb-node-reptitle.png

這個Node.js實現的爬蟲就是這樣了,祝大家能爬到自己想要的資料;)

個人建了前端學習群,旨在一起學習前端。純淨、純粹技術討論,非前端人員勿擾!入群加我微信iamaixiaoxiao。