如何使用javascript创建递归刮刀?

如何使用javascript创建递归刮刀?,javascript,node.js,asynchronous,web-scraping,Javascript,Node.js,Asynchronous,Web Scraping,所以我做了一个小刮刀用于学习目的,最后我应该在网站上得到一个树状的页面结构 我一直在绞尽脑汁想把请求弄对。这或多或少就是我所拥有的: var request = require('request'); function scanPage(url) { // request the page at given url: request.get(url, function(err, res, body) { var pageObject = {}; /* [..

所以我做了一个小刮刀用于学习目的,最后我应该在网站上得到一个树状的页面结构

我一直在绞尽脑汁想把请求弄对。这或多或少就是我所拥有的:

var request = require('request');


function scanPage(url) {

  // request the page at given url:


  request.get(url, function(err, res, body) {

    var pageObject = {};

    /* [... Jquery mumbo-jumbo to

        1. Fill the page object with information and
        2. Get the links on that page and store them into arrayOfLinks 

    */

    var arrayOfLinks = ['url1', 'url2', 'url3'];

    for (var i = 0; i < arrayOfLinks.length; i++) {

      pageObj[arrayOfLinks[i]] = scanPage[arrayOfLinks[i]];

    }
  });

    return pageObj;
}
var request=require('request');
函数扫描页(url){
//请求给定url处的页面:
get(url、函数(err、res、body){
var pageObject={};
/*[…Jquery mumbo jumbo to
1.在页面对象中填充信息和
2.获取该页面上的链接并将其存储到arrayOfLinks中
*/
var arrayOfLinks=['url1','url2','url3'];
对于(变量i=0;i
我知道这段代码在很多方面都是错误的,但它应该能让你了解我在做什么

我应该如何修改它以使其工作?(如果可能,不使用承诺)


(你可以假设网站有一个树状结构,因此每个页面都只有指向三个页面下方页面的链接,因此采用递归方法)

我知道无论出于什么原因,你都不愿意使用承诺(因为我是新手,所以我不能在评论中问为什么),但我相信承诺是实现这一点的最佳方式

下面是一个使用承诺的解决方案,可以回答您的问题,但可能不是您所需要的:

var request = require('request');
var Promise = require('bluebird');
var get = Promise.promisify(request.get);

var maxConnections = 1; // maximum number of concurrent connections

function scanPage(url) {

    // request the page at given url:

    return get(url).then((res) => {

        var body = res.body;

        /* [... Jquery mumbo-jumbo to

        1. Fill the page object with information and
        2. Get the links on that page and store them into arrayOfLinks

        */

        var arrayOfLinks = ['url1', 'url2', 'url3'];

        return Promise.map(arrayOfLinks, scanPage, { concurrency: maxConnections })
                            .then(results => {
                                var res = {};
                                for (var i = 0; i < results.length; i++)
                                    res[arrayOfLinks[i]] = results[i];
                                return res;
                            });

    });

}

scanPage("http://example.com/").then((res) => {
    // do whatever with res
});
var request=require('request');
风险值承诺=要求(“蓝鸟”);
var get=Promise.promisify(request.get);
var maxConnections=1;//最大并发连接数
函数扫描页(url){
//请求给定url处的页面:
返回get(url)。然后((res)=>{
var body=res.body;
/*[…Jquery mumbo jumbo to
1.在页面对象中填充信息和
2.获取该页面上的链接并将其存储到arrayOfLinks中
*/
var arrayOfLinks=['url1','url2','url3'];
返回Promise.map(arrayOfLinks,scanPage,{concurrency:maxConnections})
。然后(结果=>{
var res={};
对于(var i=0;i{
//用res做任何事
});
编辑:感谢Bergi的评论,重新编写代码以避免Promise构造函数反模式


编辑:以更好的方式重写。通过使用Bluebird的
并发
选项,您可以轻松限制同时连接的数量。

您可能需要一个html解析器。尝试在谷歌上搜索类似“javascript html解析器”的内容…谢谢,但这与我的问题无关。我用cheerio(node.js jquery实现)解析html,我的问题是如何以递归方式构建我的对象。这里最大的挑战是实现递归行为,因为javascript具有异步特性。不久前,我想实现类似的功能,我决定使用AJS:嗯,我会一直尝试,直到更好的解决方案出现为止。无效!您只需承诺<代码>请求。使用它获取
,然后使用
将其余代码链接到它。然后(…)
。不要在wikipedia之类的东西上运行此操作…你可能占用了本地网络的所有带宽,加热了CPU,可能会被怀疑使用了网站或其他东西。还要尝试防止周期性链接执行类似于
url1->url2->url1->……
的操作。我已经找到了类似的解决方案,问题是ll同时请求fire,但服务器不满意(参见Patrick Roberts所说)。我尝试使用reduce()按顺序执行,但它对我来说太高级了,所以我要求使用“经典”解决方案。
var promises=arrayOfLinks.map(scanPage);