Javascript Node.js:请求一个页面并允许在抓取之前构建该页面

Javascript Node.js:请求一个页面并允许在抓取之前构建该页面,javascript,node.js,asynchronous,scrape,Javascript,Node.js,Asynchronous,Scrape,我已经看到了一些将askee引用到其他库(比如phantom.js)的答案,但我想知道是否可以在node.js中实现这一点 考虑到我下面的代码。它使用request请求一个网页,然后使用cheerio探索dom以刮取页面中的数据。它工作完美无瑕,如果一切按计划进行,我相信它会输出一个文件,就像我在脑海中想象的那样 问题是,为了使用ajax或jsonp异步创建我正在查看的表,我不能完全确定.jsp页面是如何工作的。 因此,在这里,我试图找到一种方法,在为新文件刮取数据之前,先“等待”加载这些数据

我已经看到了一些将askee引用到其他库(比如phantom.js)的答案,但我想知道是否可以在node.js中实现这一点

考虑到我下面的代码。它使用
request
请求一个网页,然后使用
cheerio
探索dom以
刮取页面中的数据。它工作完美无瑕,如果一切按计划进行,我相信它会输出一个文件,就像我在脑海中想象的那样

问题是,为了使用ajax或jsonp异步创建我正在查看的表,我不能完全确定.jsp页面是如何工作的。
因此,在这里,我试图找到一种方法,在为新文件刮取数据之前,先“等待”加载这些数据

var cheerio = require('cheerio'),
    request = require('request'),
    fs = require('fs');

// Go to the page in question
request({
    method: 'GET',
    url: 'http://www1.chineseshipping.com.cn/en/indices/cbcfinew.jsp'
}, function(err, response, body) {
    if (err) return console.error(err);
    // Tell Cherrio to load the HTML
    $ = cheerio.load(body);


    // Create an empty object to write to the file later    
    var toSort = {}

    // Itterate over DOM and fill the toSort object
    $('#emb table td.list_right').each(function() {
        var row = $(this).parent();     
        toSort[$(this).text()] = {
            [$("#lastdate").text()]: $(row).find(".idx1").html(),
            [$("#currdate").text()]: $(row).find(".idx2").html()            
        }
    });

    //Write/overwrite a new file
    var stream = fs.createWriteStream("/tmp/shipping.txt"); 
    var toWrite = "";

    stream.once('open', function(fd) {
        toWrite += "{\r\n"
        for(i in toSort){ 
            toWrite += "\t" + i + ": { \r\n";
                for(j in toSort[i]){
                    toWrite += "\t\t" + j + ":" + toSort[i][j] + ",\r\n";               
                }               
            toWrite += "\t" + "}, \r\n";
        }
        toWrite += "}"

        stream.write(toWrite)
        stream.end();
    });
});
预期结果是一个文本文件,其信息格式类似于JSON对象

它应该看起来像不同的例子

"QINHUANGDAO - GUANGZHOU (50,000-60,000DWT)": { 
     "2016-09-29": 26.7,
     "2016-09-30": 26.8,
}, 
但是由于名称是唯一不加载async的东西(日期和值是异步的),所以我得到了一个混乱的对象

我尝试了实际上只是在代码中的不同位置设置了一个
setTimeout
。如果脚本失败几次,只有那些有能力运行几次脚本的开发人员才会使用该脚本。因此,虽然不理想,但即使设置超时(最多5秒)也足够了

结果是设置超时不起作用。我怀疑,一旦我请求页面,当我收到它时,我就被页面的快照“按原样”卡住了,事实上,我并不是在看一个我可以等待加载其动态内容的活动对象


我一直想知道如何在包到达时拦截它们,但我对HTTP的理解还不够透彻,不知道从哪里开始。

设置超时即使增加到一小时也不会有任何影响。这里的问题是您正在对此url发出请求:

他们的服务器返回html,在这个html中有js和css导入。您的案例到此结束,您只需使用html即可。相反,浏览器知道如何使用和解析html文档,因此它能够理解javascript脚本并执行/运行它们,而这正是您的问题所在。您的程序无法理解与HTML内容有关的内容。您需要找到或编写能够运行javascript的scraper。我刚刚在stackoverflow上发现了类似的问题:


那个家伙建议说,这个工具似乎能够运行javascript。不过,它是用python编写的

您正试图删除不包含所需数据的原始页面。 加载页面时,浏览器会评估其中包含的JS代码,该代码知道从何处以及如何获取数据

第一个选项是像PhantomJS一样计算相同的代码

另一个(您似乎对此感兴趣)是调查页面的网络活动,并了解您应该执行哪些额外的请求来获取所需的数据。 就你而言,这些是:

在这两项请求中:

  • 是一个decache参数,用于防止缓存
  • jc
    是一个JS包装函数的名称,该函数应与结果()一起调用

因此,在处废弃表格模板并执行两个额外的
请求
s,您将能够将它们合并到浏览器中看到的相同数据结构中。

您的解释坚定了我的怀疑,谢谢。虽然我不能使用python,但我将研究如何解析页面。也许我可以考虑托管页面并流式传输结果,或者其他一些东西,如果你在google上搜索,比如:node.js scraper framework,你会得到很少的结果。这篇文章可能会有帮助:如果你愿意,你可以接受答案:)在你最后的评论中包含了链接,接受答案似乎是合适的。考虑编辑它的答案: