web-dev-qa-db-ja.com

PhantomJSを使用してcsvファイルをダウンロードする方法

通常のブラウザ(Chrome)を使用してWebサイトAを閲覧しているときに、Webサイト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を使用してこのファイルをダウンロードして解析します。 pageonResourceReceivedリスナーを設定して、Phantomがファイルを受信/ダウンロードするかどうかを確認します。

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

ファイル(これはpage.open( 'URL OF THE FILE')です)をダウンロードするためにPhantomリクエストを行うと、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を取得しますが、それは望ましくありません。JavaScriptを使用して解析する必要があるCSVファイルが必要です。

17
MrD

数日にわたる調査の後、いくつかの解決策があると言わざるを得ません。

  • 評価関数では、AJAXを呼び出してファイルをダウンロードしてエンコードし、このコンテンツをファントムスクリプトに戻すことができます。
  • 一部のGitHubページで利用可能なカスタムPhantomライブラリを使用できます

PhanotmJSを使用してファイルをダウンロードする必要がある場合、PhantomJSから離れてCasperJSを使用します。 CasperJSはPhantomJSに基づいていますが、はるかに優れた直感的な構文とプログラムフローを備えています。

なぜCasperJSが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関数を使用できます。

8
MrD

PhantomJSのソリューションを見つけました。これを読む discussion 私は jsfiddle を見つけました。これはjQueryのajaxメソッドを介してURLをダウンロードし、base64としてファイルをエンコードします。

ダウンロードしたいファイルはプレーンテキスト(CSV)であったため、エンコード機能を削除しました。ターゲットページには既にjQueryが含まれているため、 jQueryをターゲットページに挿入する にする必要はありませんでした。

私のコードでは、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);
12
Matthew Lock

前の2つの答えは、最終的なCSVファイルのURLを事前に知っていることを前提としています。 Javascriptで計算されたファイルへのリダイレクトを行うHTMLページへのリンクがあり、PhantomJSの外部でそのJavascriptを評価したくない場合、これは当てはまりません。オプションは次のとおりです。

  1. phantomJSをアップストリームプロキシの背後に置き、上記のアップストリームプロキシを使用してダウンロードURL(および予想されるCookieおよびRefererヘッダー)をインターセプトします。ただし、ランダムデータ「blob」ではなく、実際のダウンロードURLを明確に識別する必要があります。ページがバイナリXMLHttpRequestsも作成する場合。
  2. phantomJSの代わりにHeadless Chromeを使用して、ダウンロードしたファイルを自動的に保存できます(または、PyVirtualDisplayを備えたFirefox。これを行うか、Headless Firefoxを待つこともできます))ダウンロードが完了したときに自分で把握できるようにする必要があります(またはアップストリームプロキシを使用して完了を監視しますが、Headless Chrome/Firefoxは現在SSL証明書を無視するように設定できません。 "少なくとも Chromium issue 721739 が修正されるまで、PhantomJSのリクエストを監視するよりもHeadless Chrome/Firefoxのリクエストを監視する方がはるかに困難です。CONNECTリクエストを見ることができますが、保持されている場合生きている場合、転送が完了したことを確実に知る方法はありません);
  3. すべての未知のコンテンツタイプを_text/plain_に変更し、_Content-Disposition_ヘッダーを削除するアップストリームプロキシの背後にPhantomJSを配置します。これにより、通常の方法でPhantomJSからファイルを読み取ることができます。 tは、0バイトのバイナリで動作します。

これらの最初のオプション(PhantomJS +アップストリームプロキシ)は、PhantomJSがリモートサイトに送信するAcceptヘッダーをアップストリームプロキシが監視できる場合に簡単になります。少なくとも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()を使用するサイトによって。したがって、アップストリームプロキシが_text/html_を含むAcceptヘッダーを持つリクエストを見つけ、thisリクエストをサーバーに渡す場合CSVファイルまたはその他のHTML以外のドキュメントが作成された場合、これが保存される可能性が高くなります。

1
Silas S. Brown