我正在使用node.js编写一个爬虫。首先,我需要获取主页面以获取该页面上每个项目的URL,然后我抓取每个项目的URL以逐个获取它们的详细信息
fetchPage(url)
是获取链接的HTML文本
function fetchPage(url){
return new Promise(
(resolve,reject)=>{
agent
.get(url)
.end(function(err,res){
if (err){
reject(err);
} else{
resolve(res.text);
}
});
});
}
这是此抓取工具的全局调用
fetchPage(link).then(
(result)=>{
const urls=getUrls(result);
for (var i=0;i<5;i++){
fetchItem(urls[i].link).then(
(result)=>{
console.log('Done');
},
(error)=>console.log(error)
);
}
},
(error)=>console.log(error)
);
我在获取主页后通过getUrls
进行处理以获取所有项目的网址
fetchItem(url)
是另一个Promise
,可确保项目的每个HTML文字在被getItem
提取后通过fetchPage
进行处理
function fetchItem(url){
return new Promise(
(resolve,reject)=>{
fetchPage(url).then(
(result)=>{
getItem(result);
},
(error)=>reject(error)
);
});
}
它会抓取。它确实得到了我需要的所有物品,而且没有任何信息。
但我的代码有问题。为什么控制台没有为我记录Done
消息?
结果的顺序不正确。已爬网结果的顺序与我预期的不同,它与网站上的订单不同。
请指出我对这些异步控制有什么误解和做错了?如何确保它们的顺序?如何修复此代码以满足?
如果我想在完全抓取所有项目之后记录消息All done
,我该怎么办?确保它们按照正确的顺序完全取出?
答案 0 :(得分:2)
Done
未被调用,因为您未解析Promise
函数中创建的fetchItem
。
我想维持结果的顺序,您可能想要使用Promise.all。它还有助于在完全抓取所有项目时收到All done
消息。
我将首先使用fetchPage
将urls
转换为fetchItem
承诺数组来更改map
功能,我可以传递给Promise.all
。fetchPage(link).then(
(result)=>{
const urls=getUrls(result);
var promises = urls.map((url) => fetchItem(url.link));
Promise.all(promises).then((values) => {
console.log('All done');
console.log(values);
}, (error) => {
console.log(error);
});
},
(error)=>console.log(error)
);
像这样的东西
fetchItem
然后将解决方案添加到您的function fetchItem(url){
return new Promise(
(resolve,reject)=>{
fetchPage(url).then(
(result)=>{
resolve(getItem(result));
},
(error)=>reject(error)
);
});
}
方法。
var USState = ["Alabama", "Alaska" , "Arizona" ,"Arkansas", "California",
"Colorado", "Connecticut"];
$(document).ready(function()
{
stateselect = document.getElementById("state");
for(i=0; i < USState.length; ++i)
{
var el=document.createElement('option');
el.textContent = USState[i];
stateselect.appendChild(el);
}