前記:
想寫乙個電影天堂的爬蟲,因為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...