如何使用PhantomJS

时间:2015-07-22 13:13:01

标签: javascript http download phantomjs

当我使用普通浏览器(Chrome)浏览网站时,当我点击网站A上的链接时,Chrome会以CSV文件的形式下载报告。

当我检查服务器响应标头时,我得到以下结果:

Cache-Control:private,max-age=31536000
Connection:Keep-Alive
Content-Disposition:attachment; filename="report.csv"
Content-Encoding:gzip
Content-Language:de-DE
Content-Type:text/csv; charset=UTF-8
Date:Wed, 22 Jul 2015 12:44:30 GMT
Expires:Thu, 21 Jul 2016 12:44:30 GMT
Keep-Alive:timeout=15, max=75
Pragma:cache
Server:Apache
Transfer-Encoding:chunked
Vary:Accept-Encoding

现在,我想使用PhantomJS下载并解析此文件。我设置了page onResourceReceived监听器,看看Phantom是否会接收/下载该文件。

clientRequests.phantomPage.onResourceReceived = function(response) {
    console.log('Response (#' + response.id + ', stage "' + response.stage + '"): ' + JSON.stringify(response));
};

当我发出Phantom请求下载文件时(这是page.open('文件的URL')),我可以在Phantom日志中看到该文件已下载。这是日志:

"contentType": "text/csv; charset=UTF-8",
    "headers": {
        "name": "Date",
        "value": "Wed, 22 Jul 2015 12:57:41 GMT"
    },
    "name": "Content-Disposition",
    "value": "attachment; filename=\"report.csv\"",
    "status":200,"statusText":"OK"

我收到了文件及其内容,但是如何访问文件数据?当我打印当前的PhantomJS page对象时,我得到了页面A的HTML而我不想要它,我想要CSV文件,我需要使用JavaScript解析它。

3 个答案:

答案 0 :(得分:12)

我找到了PhantomJS的解决方案。阅读discussion我发现jsfiddle通过jQuery的ajax方法下载了一个url,并将该文件编码为base64。

我想下载的文件是纯文本(CSV),所以我删除了编码功能。我的目标页面也已包含jQuery,因此我不需要inject jQuery into the target page

我的代码假设您已经使用PhantomJS打开了要下载文件的页面,并且该页面中包含jQuery。在我的情况下,我必须首先登录该网站才能获得下载链接。

var fs = require('fs');

var page=this;

var result = page.evaluate(function() {

    var out;
    $.ajax({
        'async' : false,
        'url' : 'fullurltodownload.csv',
        'success' : function(data, status, xhr) {
            out = data;
        }
    });
    return out;

});

fs.write('mydownloadedfile.csv', result);

答案 1 :(得分:8)

经过几天的调查后,我不得不说有一些解决方案:

  • 在您的评估函数中,您可以进行AJAX调用以下载和编码您的文件,然后您可以将此内容返回到幻像脚本
  • 您可以使用某些GitHub页面上提供的自定义幻像库

如果您需要使用PhanotmJS下载文件,然后离开PhantomJS并使用CasperJS 。 CasperJS基于PhantomJS,但它具有更好,更直观的语法和程序流程。

以下是解释“Why CasperJS is better than PhantomJS”的好帖子。在这篇文章中,您可以找到有关文件下载的部分。

如何使用CasperJS下载CSV文件(即使在服务器发送标题Content-Disposition:attachment; filename='file.csv时也可以这样做)

在这里,您可以找到一些可供下载的自定义csv文件:http://captaincoffee.com.au/dump/items.csv

要使用CasperJS下载此文件,请执行以下代码:

var casper = require('casper').create();

casper.start("http://captaincoffee.com.au/dump/", function() {
    this.echo(this.getTitle())
});
casper.then(function(){
    var url = 'http://captaincoffee.com.au/dump/csv.csv';
    require('utils').dump(this.base64encode(url, 'get'));
});

casper.run();

上面的代码将下载http://captaincoffee.com.au/dump/csv.csv CSV文件,并将结果打印为base64字符串。所以这样,您甚至不必将数据下载到文件中,您将数据作为base64字符串。

如果您明确要将文件下载到文件系统,则可以使用CasperJS中提供的download函数。

答案 2 :(得分:1)

前2个答案假设您可以提前知道最终CSV文件的URL。如果链接转到HTML页面,该页面执行Javascript计算重定向到文件,并且您不想在PhantomJS之外评估该Javascript,则情况不会如此。您的选择是:

  1. 将PhantomJS置于上游代理之后,并使用所述上游代理拦截下载URL(及其预期的Cookie和Referer标头) - 但是您必须小心确定真正的下载URL而不是某些随机数据' blob'如果页面也生成二进制XMLHttpRequests;
  2. 而不是PhantomJS使用Headless Chrome,它可以自动保存下载的文件(或使用PyVirtualDisplay的Firefox,也可以设置为执行此操作,或等待Headless Firefox)并监控下载目录 - 但您必须下载完成后可以自己弄清楚(或使用上游代理监控它完成,但无头Chrome / Firefox目前无法设置为忽略SSL证书,这意味着如果网站进入"安全&# 34;监控Headless Chrome / Firefox的请求要比监控PhantomJS的请求要困难得多,至少在Chromium issue 721739修复之前;你可以看一下CONNECT请求但是如果它&# 39; s保持活着,你无法确定转移已经完成了;
  3. 将PhantomJS置于上游代理后面,将所有未知内容类型更改为text/plain并删除Content-Disposition标题,这样您就可以正常方式从PhantomJS中读取文件 - 这应该适用于CSV文件但是对于其中包含0字节的二进制文件不起作用。
  4. 如果上游代理可以监控PhantomJS发送到远程站点的Accept标头,则第一个选项(PhantomJS +上游代理)变得更容易。至少在PhantomJS版本2.1.1中,主要请求有Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,样式表请求有Accept: text/css,*/*;q=0.1,所有其他请求(图像,脚本,XMLHttpRequest)默认为Accept: */*,尽管这可以被覆盖使用XMLHttpRequest.setRequestHeader()的网站。因此,如果上游代理看到带有Accept标头的请求包含text/html,并且将请求传递给服务器,则会生成CSV文件或其他非HTML文档,那么这是一个很好的机会,这是一个可以拯救的人。