欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Nodejs爬蟲進(jìn)階教程之異步并發(fā)控制

 更新時(shí)間:2016年02月15日 09:52:53   作者:免罪體質(zhì)者  
這篇文章主要介紹了Nodejs爬蟲進(jìn)階教程之異步并發(fā)控制的相關(guān)資料,需要的朋友可以參考下

之前寫了個(gè)現(xiàn)在看來很不完美的小爬蟲,很多地方?jīng)]有處理好,比如說在知乎點(diǎn)開一個(gè)問題的時(shí)候,它的所有回答并不是全部加載好了的,當(dāng)你拉到回答的尾部時(shí),點(diǎn)擊加載更多,回答才會(huì)再加載一部分,所以說如果直接發(fā)送一個(gè)問題的請(qǐng)求鏈接,取得的頁(yè)面是不完整的。還有就是我們通過發(fā)送鏈接下載圖片的時(shí)候,是一張一張來下的,如果圖片數(shù)量太多的話,真的是下到你睡完覺它還在下,而且我們用nodejs寫的爬蟲,卻竟然沒有用到nodejs最牛逼的異步并發(fā)的特性,太浪費(fèi)了啊。

思路

這次的的爬蟲是上次那個(gè)的升級(jí)版,不過呢,上次那個(gè)雖然是簡(jiǎn)單,但是很適合新手學(xué)習(xí)啊。這次的爬蟲代碼在我的github上可以找到=>NodeSpider。

整個(gè)爬蟲的思路是這樣的:在一開始我們通過請(qǐng)求問題的鏈接抓取到部分頁(yè)面數(shù)據(jù),接下來我們?cè)诖a中模擬ajax請(qǐng)求截取剩余頁(yè)面的數(shù)據(jù),當(dāng)然在這里也是可以通過異步來實(shí)現(xiàn)并發(fā)的,對(duì)于小規(guī)模的異步流程控制,可以用這個(gè)模塊=>eventproxy,但這里我就沒有用啦!我們通過分析獲取到的頁(yè)面從中截取出所有圖片的鏈接,再通過異步并發(fā)來實(shí)現(xiàn)對(duì)這些圖片的批量下載。

抓取頁(yè)面初始的數(shù)據(jù)很簡(jiǎn)單啊,這里就不做多解釋啦

/*獲取首屏所有圖片鏈接*/
var getInitUrlList=function(){
request.get("https://www.zhihu.com/question/")
.end(function(err,res){
if(err){
console.log(err);
}else{
var $=cheerio.load(res.text);
var answerList=$(".zm-item-answer");
answerList.map(function(i,answer){
var images=$(answer).find('.zm-item-rich-text img');
images.map(function(i,image){
photos.push($(image).attr("src"));
});
});
console.log("已成功抓取"+photos.length+"張圖片的鏈接");
getIAjaxUrlList();
}
});
} 

模擬ajax請(qǐng)求獲取完整頁(yè)面

接下來就是怎么去模擬點(diǎn)擊加載更多時(shí)發(fā)出的ajax請(qǐng)求了,去知乎看一下吧!

有了這些信息,就可以來模擬發(fā)送相同的請(qǐng)求來獲得這些數(shù)據(jù)啦。

/*每隔毫秒模擬發(fā)送ajax請(qǐng)求,并獲取請(qǐng)求結(jié)果中所有的圖片鏈接*/
var getIAjaxUrlList=function(offset){
request.post("https://www.zhihu.com/node/QuestionAnswerListV")
.set(config)
.send("method=next&params=%B%url_token%%A%C%pagesize%%A%C%offset%%A" +offset+ "%D&_xsrf=adfdeee")
.end(function(err,res){
if(err){
console.log(err);
}else{
var response=JSON.parse(res.text);/*想用json的話對(duì)json序列化即可,提交json的話需要對(duì)json進(jìn)行反序列化*/
if(response.msg&&response.msg.length){
var $=cheerio.load(response.msg.join(""));/*把所有的數(shù)組元素拼接在一起,以空白符分隔,不要這樣join(),它會(huì)默認(rèn)數(shù)組元素以逗號(hào)分隔*/
var answerList=$(".zm-item-answer");
answerList.map(function(i,answer){
var images=$(answer).find('.zm-item-rich-text img');
images.map(function(i,image){
photos.push($(image).attr("src"));
});
});
setTimeout(function(){
offset+=;
console.log("已成功抓取"+photos.length+"張圖片的鏈接");
getIAjaxUrlList(offset);
},);
}else{
console.log("圖片鏈接全部獲取完畢,一共有"+photos.length+"條圖片鏈接");
// console.log(photos);
return downloadImg();
}
}
});
} 

在代碼中post這條請(qǐng)求https://www.zhihu.com/node/QuestionAnswerListV2,把原請(qǐng)求頭和請(qǐng)求參數(shù)復(fù)制下來,作為我們的請(qǐng)求頭和請(qǐng)求參數(shù),superagent的set方法可用來設(shè)置請(qǐng)求頭,send方法可以用來發(fā)送請(qǐng)求參數(shù)。我們把請(qǐng)求參數(shù)中的offset初始為20,每隔一定時(shí)間offset再加20,再重新發(fā)送請(qǐng)求,這樣就相當(dāng)于我們每隔一定時(shí)間發(fā)送了一條ajax請(qǐng)求,獲取到最新的20條數(shù)據(jù),每獲取到了數(shù)據(jù),我們?cè)賹?duì)這些數(shù)據(jù)進(jìn)行一定的處理,讓它們變成一整段的html,便于后面的提取鏈接處理。 異步并發(fā)控制下載圖片再獲取完了所有的圖片鏈接之后,即判定response.msg為空時(shí),我們就要對(duì)這些圖片進(jìn)行下載了,不可能一條一條下對(duì)不對(duì),因?yàn)槿缒闼吹降?,我們的圖片足足有

沒錯(cuò),2萬多張,不過幸好nodejs擁有神奇的單線程異步特性,我們可以同時(shí)對(duì)這些圖片進(jìn)行下載。但這個(gè)時(shí)候問題來了,聽說同時(shí)發(fā)送請(qǐng)求太多的話會(huì)被網(wǎng)站封ip噠!這是真的嗎?我不知道啊,沒試過,因?yàn)槲乙膊幌肴ピ? ̄ー ̄〃),所以這個(gè)時(shí)候我們就需要對(duì)異步并發(fā)數(shù)量進(jìn)行一些控制了。

在這里用到了一個(gè)神奇的模塊=>async,它不僅能幫我們拜托難以維護(hù)的回調(diào)金字塔惡魔,還能輕松的幫我們進(jìn)行異步流程的管理。具體看文檔啦,因?yàn)槲易约阂膊辉趺磿?huì)用,這里就只用到了一個(gè)強(qiáng)大的async.mapLimit方法。真的很厲害哦。

var requestAndwrite=function(url,callback){
request.get(url).end(function(err,res){
if(err){
console.log(err);
console.log("有一張圖片請(qǐng)求失敗啦...");
}else{
var fileName=path.basename(url);
fs.writeFile("./img/"+fileName,res.body,function(err){
if(err){
console.log(err);
console.log("有一張圖片寫入失敗啦...");
}else{
console.log("圖片下載成功啦");
callback(null,"successful !");
/*callback貌似必須調(diào)用,第二個(gè)參數(shù)將傳給下一個(gè)回調(diào)函數(shù)的result,result是一個(gè)數(shù)組*/
}
});
}
});
}
var downloadImg=function(asyncNum){
/*有一些圖片鏈接地址不完整沒有“http:”頭部,幫它們拼接完整*/
for(var i=;i<photos.length;i++){
if(photos[i].indexOf("http")===-){
photos[i]="http:"+photos[i];
}
}
console.log("即將異步并發(fā)下載圖片,當(dāng)前并發(fā)數(shù)為:"+asyncNum);
async.mapLimit(photos,asyncNum,function(photo,callback){
console.log("已有"+asyncNum+"張圖片進(jìn)入下載隊(duì)列");
requestAndwrite(photo,callback);
},function(err,result){
if(err){
console.log(err);
}else{
// console.log(result);<=會(huì)輸出一個(gè)有萬多個(gè)“successful”字符串的數(shù)組
console.log("全部已下載完畢!");
}
});
};

先看這里=>


mapLimit方法的第一個(gè)參數(shù)photos是所有圖片鏈接的數(shù)組,也是我們并發(fā)請(qǐng)求的對(duì)象,asyncNum是限制并發(fā)請(qǐng)求的數(shù)量,如果沒有這個(gè)參數(shù)的話,將會(huì)有同時(shí)兩萬多條請(qǐng)求發(fā)送過去,嗯,你的ip就會(huì)被成功的封掉,但當(dāng)我們有這個(gè)參數(shù)時(shí),比如它的值是10,則它一次就只會(huì)幫我們從數(shù)組中取10條鏈接,執(zhí)行并發(fā)的請(qǐng)求,這10條請(qǐng)求都得到響應(yīng)后,再發(fā)送下10條請(qǐng)求。告訴泥萌,并發(fā)到同時(shí)100條沒有事的,下載速度超級(jí)快,再往上就不知道咯,你們來告訴我...

以上所述給大家介紹了Nodejs爬蟲進(jìn)階教程之異步并發(fā)控制的相關(guān)知識(shí),希望對(duì)大家有所幫助。

相關(guān)文章

  • iPhone手機(jī)上搭建nodejs服務(wù)器步驟方法

    iPhone手機(jī)上搭建nodejs服務(wù)器步驟方法

    這篇文章主要介紹了iPhone手機(jī)上搭建nodejs服務(wù)器步驟方法,本文給出了詳細(xì)的操作步驟以及操作命令,需要的朋友可以參考下
    2015-07-07
  • node.js實(shí)現(xiàn)websocket的即時(shí)通訊詳解

    node.js實(shí)現(xiàn)websocket的即時(shí)通訊詳解

    這篇文章主要介紹了深入淺出講解websocket的即時(shí)通訊,服務(wù)器可以主動(dòng)向客戶端推送信息,客戶端也可以主動(dòng)向服務(wù)器發(fā)送信息,是真正的雙向平等對(duì)話,屬于服務(wù)器推送技術(shù)的一種,需要的朋友可以參考下
    2023-05-05
  • 如何用nodejs搭建代理服務(wù)器

    如何用nodejs搭建代理服務(wù)器

    這篇文章主要介紹了如何用nodejs搭建代理服務(wù)器,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • node.js遍歷目錄的方法示例

    node.js遍歷目錄的方法示例

    本篇文章主要介紹了node.js遍歷目錄的方法示例,主要介紹了同步遍歷和異步遍歷兩種方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2018-08-08
  • NodeJs操作MYSQL方法詳細(xì)介紹

    NodeJs操作MYSQL方法詳細(xì)介紹

    本章將了解如何在nodejs中操作Mysql,實(shí)際項(xiàng)目中不可能用workbench來進(jìn)行增刪改查,而是用代碼操作,接下來我們講解一下如何在 nodejs中操作Mysql
    2022-08-08
  • Nodejs 發(fā)布自己的npm包并制作成命令行工具的實(shí)例講解

    Nodejs 發(fā)布自己的npm包并制作成命令行工具的實(shí)例講解

    今天小編就為大家分享一篇Nodejs 發(fā)布自己的npm包并制作成命令行工具的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • 詳解Nodejs之npm&package.json

    詳解Nodejs之npm&package.json

    本篇文章主要介紹了詳解Nodejs之npm&package.json,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-06-06
  • 使用express獲取微信小程序二維碼小記

    使用express獲取微信小程序二維碼小記

    這篇文章主要介紹了使用express獲取微信小程序二維碼小記,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • 淺析node Async異步處理模塊用例分析及常用方法介紹

    淺析node Async異步處理模塊用例分析及常用方法介紹

    這篇文章主要介紹了淺析node Async異步處理模塊用例分析及常用方法介紹,需要的朋友可以參考下
    2017-11-11
  • 解析Node.js異常處理中domain模塊的使用方法

    解析Node.js異常處理中domain模塊的使用方法

    這篇文章主要介紹了Node.js異常處理中domain模塊的使用方法,文中最后提到了內(nèi)存泄漏的相關(guān)問題,值得注意,需要的朋友可以參考下
    2016-02-02

最新評(píng)論