摘要:為什么選擇利用來寫爬蟲呢就是因?yàn)檫@個(gè)庫(kù),全兼容語法,熟悉的話用起來真真是爽依賴選擇版的封裝了一個(gè)服務(wù)器和一個(gè)簡(jiǎn)易的客戶端解決爬取網(wǎng)頁(yè)出現(xiàn)亂碼初步實(shí)現(xiàn)既然是要爬取網(wǎng)站內(nèi)容,那我們就應(yīng)該先去看看網(wǎng)站的基本構(gòu)成選取的是電影天堂作為目標(biāo)網(wǎng)站,想要
為什么選擇利用node來寫爬蟲呢?就是因?yàn)閏heerio這個(gè)庫(kù),全兼容jQuery語法,熟悉的話用起來真真是爽
依賴選擇cheerio: Node.js 版的jQuery
http:封裝了一個(gè)HTPP服務(wù)器和一個(gè)簡(jiǎn)易的HTTP客戶端
iconv-lite:解決爬取gb2312網(wǎng)頁(yè)出現(xiàn)亂碼
初步實(shí)現(xiàn)既然是要爬取網(wǎng)站內(nèi)容,那我們就應(yīng)該先去看看網(wǎng)站的基本構(gòu)成
選取的是電影天堂作為目標(biāo)網(wǎng)站,想要去爬取所有最新電影的下載鏈接
頁(yè)面結(jié)構(gòu)如下:
我們可以看到每個(gè)電影的標(biāo)題都在一個(gè)class為ulink的a標(biāo)簽下,再往上定位,我們可以看到最外部的盒子class為co_content8
ok,可以開工了
獲取一頁(yè)電影標(biāo)題首先引入依賴,并設(shè)定需要爬取的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里面存儲(chǔ)著網(wǎng)頁(yè)的 html 內(nèi)容,將它zhuan ma傳給 cheerio.load 之后 // 就可以得到一個(gè)實(shí)現(xiàn)了 jQuery 接口的變量,將它命名為 `$` // 剩下就都是 jQuery 的內(nèi)容了 sres.on("end", function() { var titles = []; //由于咱們發(fā)現(xiàn)此網(wǎng)頁(yè)的編碼格式為gb2312,所以需要對(duì)其進(jìn)行轉(zhuǎn)碼,否則亂碼 //依據(jù):“” 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); }); });
運(yùn)行node index
結(jié)果如下
成功獲取電影title,那如果我想獲取多個(gè)頁(yè)面的title呢,總不可能一個(gè)一個(gè)url去改吧。這當(dāng)然有辦法,請(qǐng)往下看!
獲取多頁(yè)電影標(biāo)題我們只要將之前的代碼封裝成一個(gè)函數(shù)并遞歸執(zhí)行就完成了
核心代碼 index.js
var index = 1; //頁(yè)面數(shù)控制 var url = "http://www.ygdy8.net/html/gndy/dyzz/list_23_"; var titles = []; //用于保存title function getTitle(url, i) { console.log("正在獲取第" + i + "頁(yè)的內(nè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) { //為了方便只爬了兩頁(yè) getTitle(url, ++index); //遞歸執(zhí)行,頁(yè)數(shù)+1 } else { console.log(titles); console.log("Title獲取完畢!"); } }); }); } function main() { console.log("開始爬取"); getTitle(url, index); } main(); //運(yùn)行主函數(shù)
結(jié)果如下
如果是人工操作,我們需要一次操作,通過點(diǎn)擊進(jìn)入電影詳情頁(yè)才能找到下載地址
那我們通過node如何來實(shí)現(xiàn)呢
常規(guī)先來分析頁(yè)面布局
我們?nèi)绻胍獪?zhǔn)確定位到下載鏈接,需要先找到id為Zoom的div,下載鏈接就在這個(gè)div下的tr下的a標(biāo)簽內(nèi)。
那我們就再定義一個(gè)函數(shù),用于獲取下載鏈接
getBtLink()
function getBtLink(urls, n) { //urls里面包含著所有詳情頁(yè)的地址 console.log("正在獲取第" + n + "個(gè)url的內(nèi)容"); 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"); //進(jìn)行轉(zhuǎn)碼 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); } }); }); }
再次運(yùn)行 node index
就這樣我們將3個(gè)頁(yè)面內(nèi)所有電影的下載鏈接獲取完畢,是不是很簡(jiǎn)單?
保存數(shù)據(jù)我們講這些數(shù)據(jù)爬取出來當(dāng)然是要進(jìn)行保存的啊,在這里我選用了MongoDB來對(duì)其進(jìn)行保存處理
數(shù)據(jù)保存函數(shù) save()
function save() { var MongoClient = require("mongodb").MongoClient; //導(dǎo)入依賴 MongoClient.connect(mongo_url, function (err, db) { if (err) { console.error(err); return; } else { console.log("成功連接數(shù)據(jù)庫(kù)"); var collection = db.collection("node-reptitle"); collection.insertMany(btLink, function (err,result) { //插入數(shù)據(jù) if (err) { console.error(err); } else { console.log("保存數(shù)據(jù)成功"); } }) db.close(); } }); }
這里的操作很簡(jiǎn)單,就沒必要上mongoose啦
再次運(yùn)行 node index
這個(gè)Node.js實(shí)現(xiàn)的爬蟲就是這樣了,祝大家能爬到自己想要的數(shù)據(jù);)
最后附上源碼地址:https://github.com/HuangXiZho...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/88184.html
摘要:未授權(quán)的爬蟲抓取程序是危害原創(chuàng)內(nèi)容生態(tài)的一大元兇,因此要保護(hù)網(wǎng)站的內(nèi)容,首先就要考慮如何反爬蟲。反爬蟲的銀彈目前的反抓取機(jī)器人檢查手段,最可靠的還是驗(yàn)證碼技術(shù)。機(jī)器人協(xié)議除此之外,在爬蟲抓取技術(shù)領(lǐng)域還有一個(gè)白道的手段,叫做協(xié)議。 本文首發(fā)于我的個(gè)人博客,同步發(fā)布于SegmentFault專欄,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處,商業(yè)轉(zhuǎn)載請(qǐng)閱讀原文鏈接里的法律聲明。 web是一個(gè)開放的平臺(tái),這也奠定了...
摘要:前端日?qǐng)?bào)精選你可能不知道的前端知識(shí)點(diǎn)譯在服務(wù)端渲染的實(shí)現(xiàn)掘金小前端創(chuàng)建或文件并瀏覽器導(dǎo)出下載張?chǎng)涡聆慰臻g鑫生活代理服務(wù)器淺析知乎專欄快速打造簡(jiǎn)易高效的配置掘金中文譯組件解耦之道楓上霧棋的日志第期什么樣的工程師才能算老司機(jī) 2017-07-05 前端日?qǐng)?bào) 精選 你可能不知道的前端知識(shí)點(diǎn)[譯] React 在服務(wù)端渲染的實(shí)現(xiàn) - 掘金小tip:JS前端創(chuàng)建html或json文件并瀏覽器導(dǎo)出...
摘要:寫此文的目的是為了總結(jié)在開發(fā)中能增加我們開發(fā)速度及能給我們帶來方便的工具與網(wǎng)站及一些小眾框架只限于簡(jiǎn)介不負(fù)責(zé)教程如有相應(yīng)的教程希望大家自薦或推薦我在這里感激不盡讓我們發(fā)現(xiàn)美并記錄它第一次寫文章請(qǐng)多多包涵如有我沒有寫到的但又是一些好用的工具及 寫此文的目的是為了總結(jié)在開發(fā)中能增加我們開發(fā)速度及能給我們帶來方便的工具與網(wǎng)站及一些小眾框架只限于簡(jiǎn)介不負(fù)責(zé)教程如有相應(yīng)的教程希望大家自薦或推薦我...
摘要:寫此文的目的是為了總結(jié)在開發(fā)中能增加我們開發(fā)速度及能給我們帶來方便的工具與網(wǎng)站及一些小眾框架只限于簡(jiǎn)介不負(fù)責(zé)教程如有相應(yīng)的教程希望大家自薦或推薦我在這里感激不盡讓我們發(fā)現(xiàn)美并記錄它第一次寫文章請(qǐng)多多包涵如有我沒有寫到的但又是一些好用的工具及 寫此文的目的是為了總結(jié)在開發(fā)中能增加我們開發(fā)速度及能給我們帶來方便的工具與網(wǎng)站及一些小眾框架只限于簡(jiǎn)介不負(fù)責(zé)教程如有相應(yīng)的教程希望大家自薦或推薦我...
閱讀 3506·2021-10-20 13:49
閱讀 2873·2021-09-29 09:34
閱讀 3786·2021-09-01 11:29
閱讀 3143·2019-08-30 11:01
閱讀 916·2019-08-29 17:10
閱讀 951·2019-08-29 12:48
閱讀 2846·2019-08-29 12:40
閱讀 1410·2019-08-29 12:30