【发布时间】:2016-08-08 22:14:54
【问题描述】:
我正在编写一个爬虫,它将使用 node.js 从电子商务网站获取数据。我要获取的每个输入都包含:
-
url:该链接的网址 -
directory: 以后应该写入输出文件的目录名 -
page:要查询的参数
每个页面会抓取一些item,每一个都会在后面详细抓取
这是我的 fetchPage 承诺(agent 是 require('superagent')),它将获取 HTML 文本:
function fetchPage(url,page){
return new Promise(
(resolve,reject)=>{
if (page>0){
agent
.get(url)
.send('page='+page)
.end(function(err,res){
if (err){
reject(err);
} else{
resolve(res.text);
}
});
} else{
agent
.get(url)
.end(function(err,res){
if (err){
reject(err);
} else{
resolve(res.text);
}
});
}
});
}
全球调用:
var data=[];
for (var i=1;i<=links[0].numOfPages;i++){
data.push({
url:links[0].url,
directory:links[0].directory,
page:i
});
}
const promises=data.reduce(
(promise,data)=>promise.then(()=>{
fetchPage(data.url,data.page).then(
(result)=>{
const urls=getUrls(result);
Promise.all(urls.map((url,i)=>fetchPage(url,0).then(
(result)=>{
var item=getItem(result);
item.url=url;
writeItem(item,data.directory,data.page,i+1);
},
(error)=>console.log(error)
)));
});
}),
Promise.resolve());
promises.then((values)=>console.log('All done'));
您将看到 3 个功能作为实用程序(它们都可以正常工作):
-
getUrls: 处理一个页面的 HTML 文本,返回一个 url 的数组 稍后详细抓取的项目 -
getItem: 处理一个 HTML 文本 item的详细页面,返回一个将被写入的对象 文件 -
writeItem:将对象写入文件,提供目录 和页码以制作正确的目录并写入和存储
我遇到了一个问题:
- 如何使用一个 promise 队列重建它,其中每个 promise 会一个接一个的有序运行 同步并且只允许有限数量的 Promise 并发运行?
如何正确高效地完成它?我应该如何使用这些当前代码进行更改?我也需要一些演示
我删除了fetchItem函数,因为它没有必要(实际上是用page = 0调用fetchPage),现在我只使用fetchPage
【问题讨论】:
-
您在 for 循环中有一个典型的异步操作案例,请参阅JavaScript closure inside loops – simple practical example。使用
let page而不是var page作为一个非常简单的解决方案。
标签: javascript node.js asynchronous promise web-crawler