爲何選擇利用node來寫爬蟲呢?就是由於cheerio這個庫,全兼容jQuery語法,熟悉的話用起來真真是爽html
cheerio: Node.js 版的jQuerynode
http:封裝了一個HTPP服務器和一個簡易的HTTP客戶端git
iconv-lite:解決爬取gb2312網頁出現亂碼github
既然是要爬取網站內容,那咱們就應該先去看看網站的基本構成
選取的是電影天堂做爲目標網站,想要去爬取全部最新電影的下載連接mongodb
頁面結構以下:數據庫
咱們能夠看到每一個電影的標題都在一個class
爲ulink
的a
標籤下,再往上定位,咱們能夠看到最外部的盒子class
爲co_content8
npm
ok,能夠開工了服務器
首先引入依賴,並設定須要爬取的urlmongoose
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
結果以下
成功獲取電影title,那若是我想獲取多個頁面的title呢,總不可能一個一個url去改吧。這固然有辦法,請往下看!
咱們只要將以前的代碼封裝成一個函數並遞歸執行就完成了
核心代碼 index.js
var index = 1; //頁面數控制 var url = 'http://www.ygdy8.net/html/gndy/dyzz/list_23_'; var titles = []; //用於保存title function 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如何來實現呢
常規先來分析頁面佈局
咱們若是想要準肯定位到下載連接,須要先找到id
爲Zoom
的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
就這樣咱們將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
這個Node.js實現的爬蟲就是這樣了,祝你們能爬到本身想要的數據;)
最後附上源碼地址:https://github.com/HuangXiZho...