17

我想下载一个 CSV 文件,它是通过 POST 请求单击按钮生成的。我在 casperJs 和 phantomJS 论坛上尽我所能进行了研究,结果空手而归。在像火狐这样的普通浏览器中,在发布请求之后会出现一个浏览器下载对话框窗口。如何在 PhantomJS 中处理这种情况

TTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/7.5
Content-disposition: attachment;filename=ExportData.csv
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
Date: Fri, 19 Apr 2013 23:26:40 GMT
Content-Length: 65183
4

4 回答 4

8

我找到了一种使用 casperjs 的方法(如果您使用 XMLHttpRequest 实现下载功能,它应该单独与 phantomjs 一起使用,但我没有尝试过)。

我会给你留下一个工作示例,它试图从这个页面下载最新的 PDF 。当您单击下载链接时,会触发一些 javascript 代码,这些代码会生成一些隐藏的输入字段,然后将其发布。

我们所做的是替换表单的 onsubmit 函数,使其取消提交,并获取表单目标(操作)及其所有字段。我们稍后会使用此信息进行实际下载。

var casper=require('casper').create();
casper.start("https://sede.gobcan.es/tributos/jsf/publico/notificaciones/comparecencia/ultimosanuncios.jsp", function() {

    var theFormRequest = this.page.evaluate(function() {
        var request = {}; 
        var formDom = document.forms["resultadoUltimasNotif"];
        formDom.onsubmit = function() {
            //iterate the form fields
            var data = {};
            for(var i = 0; i < formDom.elements.length; i++) {
               data[formDom.elements[i].name] = formDom.elements[i].value;
            }
            request.action = formDom.action;
            request.data = data;
            return false; //Stop form submission
        }

        //Trigger the click on the link.
        var link = $("table.listado tbody tr:first a");
        link.click();

        return request; //Return the form data to casper
    });

    //Start the download
    casper.download(theFormRequest.action, "downloaded_file.pdf", "POST", theFormRequest.data);
});

casper.run(); 

注意:您必须使用 --ignore-ssl-errors 运行它,因为它们使用的 CA 不在您的浏览器默认 CA 列表中。

casperjs --ignore-ssl-errors=true downloadscript.js
于 2014-05-07T15:26:56.643 回答
3

page.resource.received您可以在收到事件和download()文件时收听:

casper.on('page.resource.received', function(resource) {
    if (resource.stage !== "end") {
        return;
    }
    if (resource.url.indexOf('ExportData.csv') > -1) {
        this.download(resource.url, 'ExportData.csv');
    }
});
于 2013-05-09T15:47:29.717 回答
2

@julianjm 方法几乎是解决方案,但就我而言,我没有正确的表单名称来替换表单提交。

所以我找到了另一个使用 phantomjs beta 的解决方案:

有一个 phantomjs 2.0 的 beta 版本,其中包含一个解决此问题的事件处理程序。

它仍然是一个测试版,所以没有调试。

所以我在发布版本上开发了点击和页面处理,然后更改了幻像版本以使下载工作。

 casper.start('http://www.website.com.br/', function() {
    this.page.onFileDownload = function(status){console.log('onFileDownload(' + status + ')'); 

//SYSTEM WILL DETECT THE DOWNLOAD, BUT YOU WILL HAVE TO NAME THE FILE BY YOURSLEF!!
return "ContactList_08-25-14.csv"; };

    });
      casper.then(function() {
        //DO YOUR STUFF HERE TO CLICK ON THE DOWNLOAD LINK. 
      });
    casper.run();

下载: Phantom 2.0 BETA

下载exe,将phantom.exe的release版本重命名为phantom.bkp.exe,在这个地方插入这个2.0版本。然后,在 casperjs 中,您需要在 casperjs/bin/bootstrap.js 的开头添加一些行

 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */
var system = require('system');
    var argsdeprecated = system.args;
    argsdeprecated.shift();
    phantom.args = argsdeprecated;

还注释版本检查(同一文件):

(function(version) {
        // required version check
      /*  if (version.major !== 1) {
            return __die('CasperJS needs PhantomJS v1.x');
        } if (version.minor < 8) {
            return __die('CasperJS needs at least PhantomJS v1.8 or later.');
        }
        if (version.minor === 8 && version.patch < 1) {
            return __die('CasperJS needs at least PhantomJS v1.8.1 or later.');
        } */
    })(phantom.version);

请记住,这是一个调整!

因此,如果您想运行 phantom 发行版或 slimerjs,则 bootstrap 上的这些行会导致问题。

所以开发发布版本,而不是调整到这个版本才能下载。如果需要调试,则必须删除 bootstrap.js 的行

于 2015-06-29T19:33:00.300 回答
0

我必须处理一个用某种 ASP.Net 框架编写的站点,该框架在每个请求中发送大量的 POST 数据(大约 100 Kb 的数据,其中大约 95 个似乎从未在请求​​之间改变 - 显然与视口状态相关) .

但是,我找不到任何适合我的方法。我已经研究过拦截 XHR,我什至发现有人正在处理相同的框架(至少从选择器来看)但有一个更简单的案例,受这个问题的启发。我发现在过去,这不能用 PhantomJS 完成。

我的问题是单击按钮会启动一系列 AJAX 请求,最终发送这个巨大的 POST 表单,最后服务器用“Content-Disposition:附件”回复。

最后,我发现这种方法对我有用,即使它是网络效率低下的:

...setting up everything, until I just need to click on a button...

phantomData    = null;
phantomRequest = null;

// Here, I just recognize the form being submitted and copy it.

casper.on('resource.requested', function(requestData, request) {
    for (var h in requestData.headers) {
        if (requestData.headers[h].name === 'Content-Type') {
            if (requestData.headers[h].value === 'application/x-www-form-urlencoded') {
                phantomData         = requestData;
                phantomRequest      = request;
            }
        }
    }
});

// Here, I recognize when the request has FAILED because PhantomJS does
// not support straight downloading.

casper.on('resource.received', function(resource) {
    for (var h in resource.headers) {
        if (resource.headers[h].name === 'content-disposition') {
            if (resource.stage === 'end') {
                if (phantomData) {
                    // to do: get name from resource.headers[h].value
                    casper.download(
                        resource.url,
                        "output.pdf",
                        phantomData.method,
                        phantomData.postData
                    );
                } else {
                    // Something went wrong.
                }
                // Possibly, remove listeners?
            }
        }
    }
});

// Now, click on the button and initiate the dance.
casper.click(pdfLinkSelector);

下载工作完美无缺,即使我可以看到文件被请求(和发送)两次

[debug] [phantom] Navigation requested: url=https://somesite/SomePage.aspx, type=FormSubmitted, willNavigate=true, isMainFrame=true
[debug] [application] GOT FORM, REQUEST DATA SAVED
[warning] [phantom] Loading resource failed with status=fail (HTTP 200): https://somesite/SomePage.aspx
[debug] [application] END STAGE REACHED, PHANTOMDATA PRESENT
[debug] [application] ATTEMPTING CASPERJS.DOWNLOAD
[debug] [remote] sendAJAX(): Using HTTP method: 'POST'
[debug] [phantom] Downloaded and saved resource in output.pdf
[debug] [application] TERMINATING SUCCESSFULLY
[debug] [phantom] Navigation requested: url=about:blank, type=Other, willNavigate=true, isMainFrame=true
[debug] [phantom] url changed to "about:blank"

(接下来,我可能会修改脚本以尝试request.abort()从侦听器内部调用resource.requested,设置信号量并再次调用下载器 - 我将无法获取附件文件名,但这对我来说无关紧要)。

于 2017-09-14T21:51:59.053 回答