1. nao58

    Posted

    nao58
Changes in title
+Capivara+PhantomJSでCSVをダウンロード
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,48 @@
+
+フォームやリンクからCSVをダウンロードしたい場合があるかと思いますが、PhantomJSが現行バージョンではContent-Dispositionで返ってきたレスポンスを受け取ってくれません。
+
+https://github.com/ariya/phantomjs/issues/10052
+
+とはいえ、どうしてもファイルを受け取りたい場合があったので、結構強引だけど実装してみた(実際に書いたコードは複雑なので、エッセンス部分だけ)。
+
+まず「クリックしたいボタンのPOSTをAjaxでエミュレートして結果コンテンツを戻す関数」をJavaScriptで書き、定義をぶっ込む。
+
+```ruby
+page.execute_script(%!
+ window.getCsv = function(target){
+ var efn = document.querySelector("input[value='"+target+"']");
+ if (efn) {
+ var f = efn.parentNode;
+ var es = f.getElementsByTagName("input");
+ var query_str = "";
+ for (var i=0; i<es.length; i++) {
+ var name = es[i].getAttribute('name');
+ var val = es[i].getAttribute('value');
+ if (name) {
+ query_str += name + '=' + val + '&';
+ }
+ }
+ var xhr = new XMLHttpRequest();
+ xhr.open(f.getAttribute('method'), f.getAttribute('action'), false);
+ xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+ xhr.send(query_str);
+ return xhr.responseText;
+ }else{
+ return "";
+ }
+ }
+!)
+```
+
+関数の中身は、適当に。対象ページによって全然変わってくるだろうし、jQueryなどをインジェクトしてあればもっと簡単に書けるはず。
+
+そして、必要な場面でCSVを取り出す。
+
+```ruby
+ret = page.evaluate_script("getCsv('#{target}')")
+ret.split("¥r¥n").each do |line|
+ # do something
+end
+```
+
+RubyとJavaScriptが錯綜して少しトリッキーだけど、基本的には認証やCSRF対策が施されたページでも動くはず。