最近在做一个网页爬虫,先抓取列表页面,再获取列表页所有内容页的 url,然后将所有列表页的 url 循环调用抓取方法,这样导致抓取的顺序不可控,想知道如何能够控制抓取的顺序。 例如:正在抓取 A 页面, A 页面抓取完毕;正在抓取 B 页面, B 页面抓取完毕...按这样的顺序执行。
抓取函数:
function doRequest (url) { console.log(chalk.red(`正在抓取 ${url} 的内容...`)); return new Promise ((resolve, reject) => { request .post(url) .set(headers) .charset('utf-8') .then(result => { resolve(result.text); console.log(chalk.red(`${url} 的内容抓取完毕!`)); }) .catch(err => { reject(err); }) }); }
调用
// 请求列表 doRequest('list.html') .then(cOntent=> { return this.parseList(content); // 得到所有的内容页面地址 }) // 请求内容页 .then(links => { return Promise.all(links.map(link => { return doRequest(link); })) }) .then (allCOntent=> { console.log(allContent); })
执行的结果
这个结果不是按照顺序来的。
1 soooon 2018-05-04 23:45:54 +08:00 用 async 模块串行执行吧: https://github.com/caolan/async |
![]() | 2 ashong 2018-05-04 23:48:27 +08:00 array.reduce |
3 xudaiqing 2018-05-04 23:56:06 +08:00 Bluebird 的 Promise.each 或者手动拼接 then |
![]() | 4 ashong 2018-05-05 00:07:52 +08:00 links.reduce( (promise, link) => { return promise.then( ()=>{ // do request with link }) }, Promise.resolve()).then( () =>{ // done }) |
![]() | 6 IvanLi127 2018-05-05 00:48:55 +08:00 via Android 等待上一个执行完成,再执行下一个。await 了解一下?话说回来,你为啥要顺序执行? |
7 df4VW 2018-05-05 00:52:05 +08:00 1 楼都已经回答你喽 |
9 dd0754 2018-05-05 01:14:33 +08:00 加个字段来排序不是更好?页面多了你也一个一个爬啊? |
![]() | 10 ETiV 2018-05-05 01:17:36 +08:00 via iPhone bluebird +1 |
![]() | 11 des 2018-05-05 02:15:06 +08:00 via Android 没人说正经的 for of ??? |
![]() | 13 yimity 2018-05-05 08:21:18 +08:00 via Android all 中,你给的数组的顺序是什么,最终结果就是什么顺序,但是不保证拿到结果的过程的顺序。 |
![]() | 15 des 2018-05-05 10:46:04 +08:00 via Android @yuuk520 (async function() { // 请求列表 comst links = await doRequest('list.html').then(cOntent=> { return this.parseList(content); // 得到所有的内容页面地址 }); for (const link of links) { // 请求内容页 const allCOntent= await doRequest(link); console.log(allContent); } })() |
16 yuuk OP @des 厉害!!!这样可以实现,顺便有个疑问想请教一下 doRequest('list.html').then(cOntent=> { return parseList(content); }).then(links => { links.forEach(async function(link){ const allCOntent= await doRequest(link); }); }) 这样为啥就不行呢~ |
17 yuuk OP @yuuk520 明白了。。。需要这样写 doRequest('list.html').then(cOntent=> { return parseList(content); }).then(async function(links){ for (const link of links) { const allCOntent= await doRequest(link); } }) |
18 yuuk OP 感谢各位的帮助,谢谢大家。 |
![]() | 19 ChefIsAwesome 2018-05-05 11:33:25 +08:00 via Android 你可以自己再琢磨下怎么实现一次抓几个,这几个结束后再执行后面几个。一个一个抓太慢了。 |
![]() | 20 POPOEVER 2018-05-05 12:28:01 +08:00 基于 express/koa 的话为什么不用中间件? |
![]() | 21 mrcode 2018-05-05 13:53:48 +08:00 同 #11,使用 for-of 循环解决 |
![]() | 22 orzfly 2018-05-05 14:23:44 +08:00 via Android ![]() Bluebird.mapSeries(...) Bluebird.map(..., { concurrency: 5 }) |
![]() | 23 orzfly 2018-05-05 14:24:38 +08:00 via Android |