Node非同步爬蟲引出的非同步流程控制的一些問題

2022-01-19 16:26:33 字數 4321 閱讀 9847

前記:

想寫乙個電影天堂的爬蟲,因為node很長時間落下,就想用node去寫一下。結果遇到了一些列的問題,這些問題歸根到底就是非同步流程控制的問題,在以前就一直會接觸到很多**地獄,promise為什麼會出現諸如此類的話題,現在終於是深刻體會到了!

開始的**是:

const totalpage = 1; //指定爬多少頁資料

let res = ;

//獲取頁面電影資料

function gettitlehref(url,page) );

res.on('end',function());

// console.log($);

$('.co_content8 .ulink').each(function(i,d) );

});console.log(titlehref);

});if(page <= totalpage) else

});}//獲取種子鏈結

function getlink(titlehref) );

res.on('end', function());

let reg = /.*譯  名/;

let info = '';

let bt = '';

let textinfo = $('.co_content8 #zoom p').eq(0).text();

info = textinfo.match(reg)[0];

bt = $('#zoom td').children('a').attr('href');

res.push();

console.log(res);

})//怎麼捕獲錯誤!!!

'error',function())

})// }catch(e)

});};gettitlehref(baseurl,1)

所以寫node**切記大多數都是非同步的,上面**就出了乙個問題:

當前**就不能保證下面的**, 在 res.end 後執行,因為res.end在非同步佇列裡可能沒執行完,就進入了下面的if,就算最後進入getlink後就會出現titlehref.foreach進不去的情況的,因為titlehref是空的。

當時遇到這個問題如果不考慮到非同步流程控制的解決流程的話,乙個解決方案是在each函式裡,獲取到乙個titlehref就getlink下,titilehref定義成區域性函式,getlink函式放在each裡面,這樣就保證titlehref不會是空的了。然後**如下:

const totalpage = 2; //指定爬多少頁資料

let ans = ;

//獲取頁面電影資料

function gettitlehref(url,page) = res;

let chunks = ;

res.on('data',function(chunk));

res.on('end',function());

// console.log($);

$('.co_content8 .ulink').each(function(i,d) );

getlink(titlehref);

});// console.log(ans);

});

});}// /*

//獲取種子鏈結

function getlink(titlehref) = res;

const contenttype = res.headers['content-type'];

let error;

if (statuscode !== 200) `);

} if (error)

console.log('進入getlink http');

let chunks = ;

res.on('data',function(chunk) );

res.on('end', function());

let bt = '';

bt = $('#zoom td').children('a').attr('href');

// console.log(bt);

// console.log(typeof bt)

ans.push(bt);

// cb(ans);

}catch (e)

})}).on('error', (e) => `);

});});

}};// */

for(let i = 1; i <= totalpage; i++) ;

但是這樣的**你還會發現乙個問題,我們最後儲存的bt鏈結的ans結果,列印的還是空的,同樣是非同步的問題,我們如果要存入資料庫或者需要ans資料的話,我們不知道何時返回了這個資料。

所以最終我們還是要用到es6/7提出的方案promise和async/await。

修改之後**如下:

const totalpage = 2 //指定爬多少頁資料

let ans =

//獲取頁面電影資料

function gettitlehref(url, page) = res

let chunks =

res.on('data', function(chunk) )

res.on('end', function() )

let titlehref =

$('.co_content8 .ulink').each(function(i, d) )

})resolve(getlink(titlehref))

})})

})}// /*

//獲取種子鏈結

function getlink(titlehref, cb) = res

const contenttype = res.headers['content-type']

let error

if (statuscode !== 200) `)

}if (error)

let chunks =

res.on('data', function(chunk) )

res.on('end', function() )

let bt = ''

bt = $('#zoom td')

.children('a')

.attr('href')

resolve(bt)

} catch (e)

})})

.on('error', e => )

})})

)} else

}async function main()

main()

每個函式都封裝成promise,最後在主函式中用await強制同步得到最後的結果results。(注意:1。new array出來的是稀疏陣列empty,最後fill()一下填充成undefine,2。47行傳遞的已經不是乙個只有一條資料的陣列了,而是將乙個頁面each執行完成後的彙總,所以在函式內部會有promise.all

3。93行則聊勝於無,即使return null也會正確的觸發resolve的,這麼寫只是提高一些可讀性罷了。)

promise和async/await整理可以看我的這篇部落格promise和async/await用法整理

**:github傳送

這次告訴我實踐很重要!要把所學和書中所看運用到業務和**邏輯中!

node 非同步程式設計

我了解到的node非同步程式設計可分成 1.函式 2.pub sub模式 發布 訂閱模式 3.promise 4.generator 5.async await 一.直接 函式 該方法是最直接常用的非同步操作方式,比如在setinterval 和 ajax等會使用到,存在缺點有 1.不易閱讀並且容易...

python爬蟲 非同步爬蟲

壞處 無法無限制的開啟多執行緒或者多程序。執行緒池 程序池 適當使用 使用非同步實現高效能的資料爬取操作 人多力量大 環境安裝 pip install aiohttp 使用該模組中的clientsession 2表示同時存在兩個協程 pool pool 2 urls for i in range 1...

Node教程 非同步API

導學 通過返回值拿結果 path.join 通過函式拿結果,fs.redfile 在node中有兩種api 同步的api還有非同步的api 同步所謂的同步就是一步一步的走 非同步當前的api不會堵塞後續的 的執行 對比不能通過返回值拿結果 這裡舉例說明 讀取檔案的操作是非同步的 fs.readfil...