Pixiv検索結果をCSVダウンロードするHTMLファイルを用意した

#概要
Pixivのタグ分析をするに辺り、
検索結果を機械可読性の高いCSV形式で取得する必要がある。
逐一API用のURLを用意し、CSVファイルをダウンロードするのは面倒なので、
インターフェース用のHTMLファイルを用意した。
※GoogleChrome使用を前提にしているが、
　他のブラウザでも動作すると思われる。
　複数ポップアップや複数ファイルダウンロードがブロックされたら、
　アドレスバーやタスクバーで解除する必要がある。
※NO SECURE.
　PHPSESSIDはクリエ文字列やクッキーで暗号化せずに通信される。
　ただし、R-18のイラスト・小説の取得はPHPSESSIDが必須になる。

#デモ
http://bl.ocks.org/nezuQ/raw/9719897/

#コード
```html:index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>PxCSV 〜Pixiv検索結果をCSV形式で〜</title>
</head>
<body onload="V.init();">
    <header>
        <h1>PxCSV 〜Pixiv検索結果をCSV形式で〜</h1>
    </header>
    <article>
        <span>検索サイト：</span>
        <br/>
        <select id="ddlEndpoint">
        </select>
        <br/>
        <span>検索キーワード：</span>
        <br/>
        <input type="text" id="txtQuery" style="width: 800px" />
        <br/>
        <span>検索箇所：</span>
        <br/>
        <select id="ddlSearchType">
        </select>
        <br/>
        <span>並び順：</span>
        <br/>
        <select id="ddlOrder">
        </select>
        <br/>
        <span>ページ：</span>
        <br/>
        <input type="text" id="txtMinPage" style="width: 50px" />
        <span>〜</span>
        <input type="text" id="txtMaxPage" style="width: 50px" />
        <br/>
        <span>PHPSESSID：</span>
        <br/>
        <input type="text" id="txtPHPSessID" style="width: 400px" />
        <br/>
        <br/>
        <input type="button" value="Pixiv表示" onclick="displayPage();" />
        <input type="button" value="CSV表示" onclick="displayCSV();" />
        <input id="btnCSVDownload" type="button" value="CSVダウンロード" onclick="downloadCSV();" />
    </article>
    <script>
    var URL_ENDPOINT_LIST = [
        {"id":0,"name":"Pixivイラスト","url":"http://www.pixiv.net/search.php","api":"http://spapi.pixiv.net/iphone/search.php"},
        {"id":1,"name":"Pixiv小説","url":"http://www.pixiv.net/novel/search.php","api":"http://spapi.pixiv.net/iphone/search_novel.php"}
        ];
    var SEARCH_TYPE_LIST = [
        {"id":0,"name":"タグ","key":"s_tag"},
        {"id":1,"name":"タイトル・キャプション/本文","key":"s_tc"}
        ];
    var ORDER_LIST = [
        {"id":0,"name":"新しい順","key":""},
        {"id":1,"name":"古い順","key":"&order=date"}
        ];
        
    var V = (function(){
        var ME = {};
        
        var ddlEndpoint = document.getElementById("ddlEndpoint");
        var txtQuery = document.getElementById("txtQuery");
        var ddlSearchType = document.getElementById("ddlSearchType");
        var ddlOrder = document.getElementById("ddlOrder");
        var txtMinPage = document.getElementById("txtMinPage");
        var txtMaxPage = document.getElementById("txtMaxPage");
        var txtPHPSessID = document.getElementById("txtPHPSessID");
        var btnCSVDownload = document.getElementById("btnCSVDownload");
        
        ME.getEndpointUrl = function(){return getListItemById(URL_ENDPOINT_LIST,ddlEndpoint.value)["url"];};
        ME.getEndpointApi = function(){return getListItemById(URL_ENDPOINT_LIST,ddlEndpoint.value)["api"];};
        ME.getQuery = function(){return txtQuery.value;};
        ME.getSearchtype = function(){return getListItemById(SEARCH_TYPE_LIST,ddlSearchType.value)["key"];};
        ME.getOrder = function(){return getListItemById(ORDER_LIST,ddlOrder.value)["key"];};
        ME.getMinPage = function(){return txtMinPage.value;};
        ME.getMaxPage = function(){return txtMaxPage.value;};
        ME.getPhpsessid = function(){return txtPHPSessID.value;};
        
        ME.init = function() { 
            setOptions2Select(ddlEndpoint,URL_ENDPOINT_LIST);
            txtQuery.value = "(百合 OR ｷﾏｼﾀﾜｰ) -腐向け";
            setOptions2Select(ddlSearchType,SEARCH_TYPE_LIST);
            setOptions2Select(ddlOrder,ORDER_LIST);
            txtMinPage.value = 1;
            txtMaxPage.value = 1;
            ME.cookie2view();
            if(window.navigator.userAgent.toLowerCase().indexOf('chrome') == -1){
                btnCSVDownload.style.display = "none";
            }
        };
        
        ME.view2cookie = function(){            
            var cookieString = "PHPSESSID=" + escape(txtPHPSessID.value);
            document.cookie = cookieString;
        };
        
        ME.cookie2view = function(){
            var cookieString = unescape(document.cookie);
            var match = (/(PHPSESSID=){1}[^(;)]*/g).exec(cookieString);
            txtPHPSessID.value = match ? match[0].replace("PHPSESSID=","") : "";
        };
        
        function setOptions2Select(select,list){
            list.forEach(function(item){
                var option = document.createElement('option');
                option.value = item["id"];
                option.text = item["name"];
                select.add(option, 0);
            });
        }
        
        return ME;
    })();
    
    function displayPage(){
        var i = 1;
        createURLList(
            createURL(
                V.getEndpointUrl(),
                V.getQuery(),
                V.getSearchtype(),
                V.getOrder(),
                V.getPhpsessid()
                ),V.getMinPage(),V.getMaxPage())
            .reverse()
            .forEach(function(url){
                /* 
              * [Google Chrome]
                * アドレスバーで複数ポップアップを許可する必要がある。
                * 全リンクをポップアップで表示する。
                */
                //window.open(url, "_blank");
                setTimeout(openURL(url), 1000 * i);
                i++;
            });
            V.view2cookie();
    }

    function displayCSV(){
        var i = 1;
        createURLList(
            createURL(
                V.getEndpointApi(),
                V.getQuery(),
                V.getSearchtype(),
                V.getOrder(),
                V.getPhpsessid()
                ),V.getMinPage(),V.getMaxPage())
            .reverse()
            .forEach(function(url){
                //window.open(url, "_blank");
                setTimeout(openURL(url), 1000 * i);
                i++;
            });
            V.view2cookie();
    }
    
    function downloadCSV() {
        var i = 1;
        var minP = V.getMinPage();
        var dtString = getDateTimeString();
        createURLList(
            createURL(
                V.getEndpointApi(),
                V.getQuery(),
                V.getSearchtype(),
                V.getOrder(),
                V.getPhpsessid()
                ),minP,V.getMaxPage())
            .forEach(function(url){
                /* 
              * [Google Chrome]
                * タスクバーで複数ダウンロードを許可する必要がある。
                */
                setTimeout(
                    openURL(url,
                        V.getQuery()
                         + "_" + dtString
                         + "_" + padleft((+minP) + (+i) -1, 3, "0") 
                         + ".csv"
                      ), 1000 * i);
                i++;
            });
            V.view2cookie();
    }
    
    function getDateTimeString(){
        var d = new Date();
        return padleft(d.getYear(),2,"0") + padleft(d.getMonth(),2,"0") + padleft(d.getDate(),2,"0")
         + padleft(d.getHours(),2,"0") + padleft(d.getMinutes(),2,"0") + padleft(d.getSeconds(),2,"0");
    }
    
    function padleft(base,count,pad){
        pad = pad || " ";
        var padString = "";
        for(var i = 0;i < count;i++){
            padString += pad;
        }
        return (padString + base).slice(-count);
    }
    
    function createURL(endpoint,query,searchtype,order,phpsessid){
        return endpoint
         + "?&s_mode="
         + encodeURIComponent(searchtype) 
         + "&word=" + encodeURIComponent(query) 
         + order 
         + "&PHPSESSID=" + phpsessid;
    }
    
    function getListItemById(list,id){
        var rtn = null;
        for(var i = 0;i < list.length;i++){
            var item = list[i];
            if(item["id"] == id){
                rtn = item;
                break;
            }
        }
        return rtn;
    }
    
    function createURLList(url,minPage,maxPage){
        var rtn = [];
        if(minPage <= maxPage){
            for(var i = minPage;i <= maxPage;i++){
                rtn.push(url + "&p=" + i);
            }
        }
        return rtn;
    }
    
    function openURL(url,filename){
        var a = document.createElement('a');
        a.href = url;
        a.target = "_blank";
        if(filename){
            a.setAttribute("download", filename);
        }
        document.body.appendChild(a);
        setTimeout(function() {
            a.click();
            document.body.removeChild(a);
            }, 70);
    }
    
    </script>
    </body>
</html>


<!--
PxCSV

Copyright (c) 2014 nezuq

This software is released under the MIT License.

http://opensource.org/licenses/mit-license.php
-->
```

#関連ページ
[ -> Pixivイラスト検索APIの取得結果のデータ構造を調べる](http://qiita.com/nezuq/items/e4c55bb9c68bf5785e73)
[ -> 複数のCSVファイルを1ファイルにまとめるコマンド](http://qiita.com/nezuq/items/4a098616feeb9c62e6a2)
#対象サイト
[ -> [pixiv]](http://www.pixiv.net/)