ぷち系DL回収作業メモとスクリプト
回収作業に当たり、やって頂きたい事
【注】12/26 時点 : ぷちデレラに関する回収タスクは現在ありません
「スクリプト(コード)の実行ってどうやるの?」という方は、
まず最初に リンク先記事の [Tips-2] スクリプト実行 解説部分をお読みください
https://tech.packetroom.net/imcg-idol-data-dl-complement
※ DLファイル数が多い場合、ブラウザから複数DLの許可を求められるケースがあるので、都度応じてください。
-
[Task-1] 各エピソードリストDLを一括実行 & 開放済ぷち確認
まず 本記事ページ中ほどに掲載されている [A-1] 部分のコードをコピーし、
それを ぷちデレラ系ページなら割とどこでも良いので DevTools の Console 上で実行。そうすると 全開放されているぷちデレラのみ
petit_episode_list_{アイドル名}.json
がDLされる。
最後に、その結果をまとめた.txt
ログも出力される。
この [Task-1] 作業は1回で完了 -
[Task-2] (開放済みの)ぷちデレラ別でDL回収
上記 [Task-1] ( =[A-1]実行 ) により
〇〇.json
へ書き出された各ぷちデレラ
( つまり、 結果ログ.txt
に 「開放済み 〇」 の記載があるぷちデレラ )
...が、LvMAX + テクニカルボード全開放 を満たしている 適合ぷちデレラ となります。
※ 適合していても、既に回収表が埋まっている場合は対象外です。
※ 確認に必要な 「エピソード系回収リスト」 は、本記事の中ほどをご覧ください。回収手順は以下。
まず、[B-1] で提示されているコードを実行。
すると{ぷちデレラID}_{エピソード数}.flashext
が 8つ および
{ぷちデレラID}_petit_serif.json
ファイルが 1つ DLされるはず。本 [Task-2] におけるDL作業は、回収対象のぷちプロフページごとに都度実行してください。
※ 後述の理由から、まず対象ぷちデレラ分の .flashext を一気にDLしておく事を推奨
-
[Task-3] フォルダ分け & リネーム作業
上記[Task-1]と[Task-2]の順次実行をすべて終えると、
ぷちデレラ1体分につき、以下のファイルが出そろうはずです。{ぷちデレラID}_{エピソード数}.flashext
( .swf ) x 8個{ぷちID}_petit_serif.json
x 1個petit_episode_list_{アイドル名}.json
x 1個
お手間でなければ、以下ルールに則った、
リネーム & ぷちデレラ別フォルダ分け 作業 もお願いします。-
[Task-3.1] 拡張子変更作業
.flashext
の拡張子を全て.swf
へ変更してください。
※ 下記手順を踏むと一瞬で終わります(1) DLした全ての
.flashext
を、適当なフォルダへ一旦ごっそり移動。
(2) そのフォルダ内で適当なテキストファイル.txt
を作成 + 下記内容コピペで保存。
▼ ファイル内容はこの1行だけren *.flashext *.swf
※「この命令文みたいなの何?」と不安な方は、一度ググって頂ければと。
(3) そのまま拡張子を
.txt
から.bat
へ変更し、その場でダブルクリック実行。
こうすると、その階層の.flashext
拡張子が全て.swf
に変更されます。
( ※ フォルダ分け前にこの作業をすれば、一度の実行で済みます )- ※ 拡張子を .swf でDLしない理由
元から.swf
でもDL出来るのですが、その場合ブラウザから危険なファイルとして扱われ、
都度 DL許可作業 を挟まなければいけない為、手間削減の観点から偽装DLしています。
( 拡張子変更なら、上記.bat
の利用ですぐ終わる...というのも理由です )
- ※ 拡張子を .swf でDLしない理由
-
[Task-3.2] フォルダ分け と配置
ぷちデレラID別のフォルダ(
1xxx
のような半角の4桁数字となる)を作り、そこへ対象ぷちデレラの
{ぷちID}_{エピ数}.flashext
( もとい.swf
)ファイル 8つ のみ を配置petit_episode_list_{アイドル名}.json
および
{ぷちID}_petit_serif.json
の2種は ぷちデレラ別のフォルダに混入させず、
「エピソードリスト用」と「セリフ用」のフォルダを2つだけ作成し、
そこへ全アイドル分をまとめて一括格納して頂けると助かります。
-
[Task-4] チャンネル内にぶん投げる
なんか適当に.zip
とかで圧縮して、チャンネルにご報告兼ねて投げて頂ければと。
Discordの仕様上、あんまり大きなファイルをドンと置けないらしく、
複数ぷちデレラにわたって一気に作業回収された場合、4体ほど?に小分けにしておくと躓かずuploadできそうです。
ぷちエピソードリスト(一括/個別)取得
ぷちエピソードの開放確認用APIのリザルトを回収DL保存
[A-1] 全員一括DL + 確認版
- 実行場ページ
ぷちデレラ系ページなら多分どこでも?
実行中のページ上 ( ※ DeVtool上ではない ) でEsc
キーを押すと、以降のDLが中断破棄 - 概要 / 動作内容
このスクリプトを実行すると「ぷちデレラのぷちエピソード開放具合」を問い合わせるAPIに対し、
実装済ぷちデレラ全員( 卯月~颯 までの193人分 )のアクセスおよびそのDL回収を試みます。
現行DLフォーマットはpetit_episode_list_{アイドル名}.json
です。
エピ解放済みぷちデレラのみ DLされ、それ以外はスキップされます。
( ※ エピソード全開放がDL条件です ) -
補足用のtxtファイル
行程終了後、以下の結果まとめが.txt
でDLされます。 ( 通知ボイス再生 + Console にも表示 )ぷちID 属性 アイドル名 DLまたは開放状況 4桁の数字 属性 未加入だと未記載 〇
... 少なくともエピはコンプ済みなのでDL完了 (.json
が得られている筈 )△
... ぷちは所属しているが、エピソード未コンプ
×
... そもそもぷちデレラ未加入
余談ですが、ぷちセリフ(コメント系)は Lv30+ボード全開放が条件となっています。
このセクションではエピソードリストのDLなので、テクニカルボード上のエピを全開放していればいけるハズ
( そもそもの内部処理で、全開放=8種類 無ければDLしないようになっています )
[Script : A-1] ぷちエピソードリストDL取得 / 対象一括DL版
(async function(){
const _dlTargetDefObj = [];
let _appendCount = 192; // 最初の一人 + 192 = 193人分 (卯月~颯)
window.isFileDlStop = false;
for(let _n=0; _appendCount>_n; _n++){
const _targetVal = (1001 + _n); // 基点番号
const _url = `https://sp.pf.mbga.jp/12008305/?guid=ON&url=http%3A%2F%2Fmobamas.net%2Fidolmaster%2Fpetit_cg%2Fajax_episode_list`;
// ファイル名基本フォーマット (拡張子除く)
const _saveFileFormatName = `petit_episode_list_${_targetVal}`;
const _postObj = { "idol_id" : _targetVal };
_dlTargetDefObj.push( { "filename" : _saveFileFormatName , "url" : _url , "PostObject" : _postObj , "petit_id" : _targetVal } );
}
const _resultMap = new Map();
console.info("=================================================");
console.info("DL処理を開始します。 中止したい場合はページ上で Esc(エスケープキー) を押してください");
console.info("=================================================");
console.info(`DL予定数合計 : ${_appendCount}`);
const _arrtDefArr = ["*","Cute","Cool","Passion"]; // 属性定義
function _fileDl(_dlInfo , _index) {
return new Promise((resolve,reject) => {
const _fileName = _dlInfo.filename;
const _url = _dlInfo.url;
if(window.isFileDlStop){
console.info("以降のDLを全て中止します");
reject();
return;
}
setTimeout(() => {
const _req = new XMLHttpRequest();
_req.open("POST", _url , true);
_req.responseType = "json";
_req.onload = function(oEvent) {
const _data = _req.response;
try{
const _setPetitId = _dlInfo["petit_id"];
const _setAttr = _data?.["idol_attribute"] || 0;
let _setNname = "";
let _setDlCheck = "";
if(_data?.episode_list?.length >= 8){ // エピソード数は8個
const _name = _data.episode_list[0]["episode_name"].match(/([\W]*)/)[1];
const _blob = new Blob([JSON.stringify(_data,null,"\t")] , {type: "application\/json"});
const _dlUrl = URL.createObjectURL(_blob);
const _a = document.createElement('a');
_a.href = _dlUrl;
_a.download = `${_fileName}_${_name}.json`;
document.body.appendChild(_a);
_a.click();
document.body.removeChild(_a);
URL.revokeObjectURL(_dlUrl);
_setDlCheck = "〇";
_setNname = _name;
console.info(`${_setDlCheck} ${_a.download} : ${_blob.size} byte ${_index+1} 個目のDLが完了しました`);
}else{
if(_setAttr == 0){
_setDlCheck = "×";
console.log(_setDlCheck , _setPetitId , "は ぷちデレラ未加入と判断されました");
}else{
_setDlCheck = "△";
console.log(_setDlCheck , _setPetitId , "は Lvまたはボード等が未コンプ状態と判断されました");
}
}
// ぷちIDをキーとして [ 属性, (得られれば)名前 , (DL出来たなら)DL成功の旨 ] の配列をMAP格納
_resultMap.set( _setPetitId , [ _arrtDefArr[_setAttr] , _setNname , _setDlCheck]);
}catch(_e){
console.warn(_e);
}
resolve();
};
const _formData = new FormData();
// POST あり
if(_dlInfo["PostObject"]){
const _pObjs = _dlInfo["PostObject"];
for(const _keyName in _pObjs){
const _val = _pObjs[_keyName];
_formData.append( _keyName , _val );
}
_req.send( _formData );
}
else{
_req.send();
}
}, 100); // DL間隔ミリ秒。あまり縮めないほうが良い
});
}
// 実処理開始
(async () => {
await _dlTargetDefObj.reduce((promise, _dlInfo , _currentIndex) => {
return promise.then(async () => {
await _fileDl(_dlInfo , _currentIndex);
});
}, Promise.resolve());
console.info("=== 予約中のデータを全てDLしたと判断されました ====");
{
//console.table(_resultMap);
let _outStr = "ぷちID / 属性(または未加入) / アイドル名 / DL(=エピソード一覧json取得)状況\n※ タブで整形されているので、Excel等にそのまま貼り付けられます\n\n";
_resultMap.forEach((_e , _key)=>{
_outStr += ( _key + "\t" + _e.join("\t") ) + "\n";
});
console.log(_outStr);
const _dlUrl = URL.createObjectURL( new Blob([_outStr+"\n\n"] , {type: "text/plain"}) );
const _a = document.createElement('a');
_a.href = _dlUrl;
_a.download = `_ぷちエピソードDL成功一覧.txt`;
document.body.appendChild(_a);
_a.click();
document.body.removeChild(_a);
URL.revokeObjectURL(_dlUrl);
}
// 全DL完了時処理
{
const _file = "https://resource.mobamas.net/idolmaster/sound/3207601/637e9bda8de8a884cf5ee0f9b695d5f8.mp4";
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
fetch(_file).then(_res=>{
return _res.arrayBuffer();
}).then(_arrayBuffer => {
audioContext.decodeAudioData(_arrayBuffer , _audioBuffer =>{
const _source = audioContext.createBufferSource();
_source.buffer = _audioBuffer;
const _gainNode = audioContext.createGain();
_source.connect(_gainNode);
_gainNode.connect(audioContext.destination);
_gainNode.gain.value = 0.2; // 音量
_source.start(0);
});
});
}
})();
// DL中止用
document.body.addEventListener("keydown" , e=>{
if (e.code === "Escape") {
window.isFileDlStop = true;
}
});
})();
[A-Sub] 個別DL版
- 実行ページ
個々のぷちプロフページ
※ 「ぷちめにゅー」 から 「リスト」 経由で ぷちプロフに移動 ( 着せ替え用ページ ) - 概要 / 動作内容
ほとんどの動作や仕様は、前項の [A-1] 全員一括版と変わりません。
大きな違いとして、そのぷちデレラのみ対象として、エピソードリストの.json
をDLします。
※ 未開放の場合は当然DLに失敗します。
[Script : A-sub] ぷちエピソードリストDL / 個別実行版 ( ※ [A-1] が正しく実行済みなら不要 )
(async function(){
const _m = location.href.match(/%2Fpetit_cg%2Fcoordinate_idol%2F([\d]*)/);
let _isDlFlag = false;
if(!_m || !_m?.[1]){
console.info(_m?.[1]);
window.alert("個別のぷちプロフページで実行してください");
return;
}
const _targetVal = _m[1];
console.info(_targetVal);
const _url = `https://sp.pf.mbga.jp/12008305/?guid=ON&url=http%3A%2F%2Fmobamas.net%2Fidolmaster%2Fpetit_cg%2Fajax_episode_list`;
const _saveFileFormatName = `petit_episode_list_${_targetVal}`;
const _postObj = { "idol_id" : _targetVal };
const _dlTargetDefObj = { "filename" : _saveFileFormatName , "url" : _url , "PostObject" : _postObj , "petit_id" : _targetVal };
async function _fileDl(_dlInfo) {
const _req = new XMLHttpRequest();
_req.open("POST", _url , true);
_req.responseType = "json";
_req.onload = function(oEvent) {
const _data = _req.response;
try{
const _setPetitId = _dlInfo["petit_id"];
const _setAttr = _data?.["idol_attribute"] || 0;
const _fileName = _dlInfo.filename;
let _setNname = "";
let _setDlCheck = "";
if(_data?.episode_list?.length >= 8){ // エピソード数は8個
const _name = _data.episode_list[0]["episode_name"].match(/([\W]*)/)[1];
const _blob = new Blob([JSON.stringify(_data,null,"\t")] , {type: "application\/json"});
const _dlUrl = URL.createObjectURL(_blob);
const _a = document.createElement('a');
_a.href = _dlUrl;
_a.download = `${_fileName}_${_name}.json`;
document.body.appendChild(_a);
_a.click();
document.body.removeChild(_a);
URL.revokeObjectURL(_dlUrl);
_setDlCheck = "〇";
_setNname = _name;
console.info(`${_setDlCheck} ${_a.download} : ${_blob.size} byte のDLが完了しました`);
}else{
if(_setAttr == 0){
_setDlCheck = "×";
console.log(_setDlCheck , _setPetitId , "は ぷちデレラ未加入と判断されました");
}else{
_setDlCheck = "△";
console.log(_setDlCheck , _setPetitId , "は Lvまたはボード等が未コンプ状態と判断されました");
}
}
}catch(_e){
console.warn(_e);
}
};
const _formData = new FormData();
if(_dlInfo["PostObject"]){
const _pObjs = _dlInfo["PostObject"];
for(const _keyName in _pObjs){
const _val = _pObjs[_keyName];
_formData.append( _keyName , _val );
}
_req.send( _formData );
}
}
await _fileDl(_dlTargetDefObj);
})();
[B-1] 単体のぷちエピソード一括&セリフ同時DL
- 実行ページ
個々のぷちプロフページ
※ 「ぷちめにゅー」 から 「リスト」 経由で ぷちプロフに移動 ( 着せ替え用ページ ) - 概要 / 動作内容
ぷちデレラのエピソード本体ファイル.swf
(.flashext
) をDL
ぷちデレラのセリフ一覧の定義ファイル.json
をDL
[Script : B-1] ぷち別エピソード.swf 一括DL および エピソードリスト.jsonのDL
(async()=>{
const _petitId = (()=>{ // URLか内部定義からぷちIDを取得
const _id = location.href.match(/%2Fpetit_cg%2Fcoordinate_idol%2F([\d]*)/)?.[1] || mc.character['1']?.idol_id;
if(_id && _id > 1000){ return _id; }
})();
if(!_petitId){ return console.error("ぷちID取得に失敗"); }
const _cmtData = comment_list;
if(!_cmtData){ return console.error("LV30+ボード全開放条件未達成されていない様です。ぷちセリフなどDLできません。"); }
if(_cmtData){ // セリフリスト即時をDL
const _url = URL.createObjectURL( new Blob([JSON.stringify(_cmtData,null,'\t')],{type:'application\/json'}) );
const _link = document.createElement("a");
//const _name = mc.character['1'].short_name;
_link.href = _url;
_link.download = `${_petitId}_petit_serif.json`;
document.body.appendChild(_link); _link.click(); document.body.removeChild(_link);
URL.revokeObjectURL(_url);
}
const _dlTargetDefArr = [];
{
// エピソードリスト取得
const _epiurl = "https://sp.pf.mbga.jp/12008305/?guid=ON&url=http%3A%2F%2Fmobamas.net%2Fidolmaster%2Fpetit_cg%2Fajax_episode_list";
const _formData = new FormData();
_formData.append('idol_id', _petitId);
const _epData = await fetch(_epiurl,{ method: "POST",body: _formData }).then(_res=>{ return _res.json(); });
console.info(_epData);
const _ep_list = _epData?.episode_list;
_ep_list.forEach(_ep=>{
console.info(_ep);
const _epNum = _ep?.episode_id;
let _saveFileFormatName = `${_petitId}_${_epNum}`;
// ボイス無しクエリURLでDL
const _dlSwfUrl = `https://sp.pf.mbga.jp/12008305/?guid=ON&url=http%3A%2F%2Fmobamas.net%2Fidolmaster%2Fpetit_cg`
+`%2Fpetit_show_episode_swf%2F${_petitId}%2F${_epNum}%2Fcoordinate_idol%2F1%2F0%2F0`;
_dlTargetDefArr.push( { "filename" : _saveFileFormatName , "url" : _dlSwfUrl , "optionExt" : ".flashext"} );
});
}
console.info(`========= DL処理を開始 計 ${_dlTargetDefArr.length} =========`);
// 実処理開始
(async () => {
await _dlTargetDefArr.reduce((promise, _dlInfo , _currentIndex) => {
return promise.then(async () => {
await _fileDl(_dlInfo , _currentIndex);
});
}, Promise.resolve());
console.info("========= 予約中のデータを全てDLしたと判断されました =========");
})();
function _fileDl(_dlInfo , _index) {
return new Promise((resolve,reject) => {
setTimeout(() => {
try{
const _fileName = _dlInfo["filename"];
const _fileUrl = _dlInfo["url"];
fetch(_fileUrl)
.then((_res)=> _res.blob())
.then((_blob)=>{
const _a = document.createElement("a");
const _dataUrl = URL.createObjectURL(_blob);
_a.href = _dataUrl;
// ファイル名+拡張子
_a.download = `${_fileName}${(_dlInfo?.optionExt?_dlInfo?.optionExt:"")}`;
document.body.appendChild(_a); _a.click(); document.body.removeChild(_a);
console.info(_a.download , `size:${_blob.size}byte , ${_index+1} 個目のDLが完了しました`);
URL.revokeObjectURL(_dataUrl);
});
}catch(_e){ console.warn(_e); }
resolve();
}, 100); // DL間隔ミリ秒。あまり縮めないほうが良い
});
}
})();
検索ネタ
( ご存じの方/知ってるけど使ってない ってほうが圧倒的に多そうですが )
- ブラウザページ上で
Ctrl+F
を実行 - 右上に検索フォームが出るので、名前を入力
- 実行すると、即時そのアイドル名へジャンプするので調べやすい
エピソード系回収リスト
ご協力により、全ぷちデレラ分を回収できました
.swfDL
... [B-1] で個別に入手可能エピリストDL
... [A-1] で一括入手可能 / 個別なら [A-Sub] がオススメセリフリストDL
... [B-1] で個別に入手可能エピボイスDL
... エピの .swf さえ手元にあれば 作者側でDL可能なので手法未記載
( 分かりやすいように記事こさえるのも大変なのれす... )
id | name | ▼.swfDL | ▼エピリストDL | ▼セリフリストDL | ▼エピボイスDL |
---|---|---|---|---|---|
1001 | 島村卯月 | ◎ | ◎ | ◎ | ◎ |
1002 | 小日向美穂 | ◎ | ◎ | ◎ | ◎ |
1003 | 西園寺琴歌 | ◎ | ◎ | ◎ | 実装なし |
1004 | 渋谷凛 | ◎ | ◎ | ◎ | ◎ |
1005 | 川島瑞樹 | ◎ | ◎ | ◎ | ◎ |
1006 | 上条春奈 | ◎ | ◎ | ◎ | ◎ |
1007 | 本田未央 | ◎ | ◎ | ◎ | ◎ |
1008 | 赤城みりあ | ◎ | ◎ | ◎ | ◎ |
1009 | 大槻唯 | ◎ | ◎ | ◎ | ◎ |
1010 | 神崎蘭子 | ◎ | ◎ | ◎ | ◎ |
1011 | 三村かな子 | ◎ | ◎ | ◎ | ◎ |
1012 | メアリー・コクラン | ◎ | ◎ | ◎ | - |
1013 | 前川みく | ◎ | ◎ | ◎ | ◎ |
1014 | 椎名法子 | ◎ | ◎ | ◎ | ◎ |
1015 | 宮本フレデリカ | ◎ | ◎ | ◎ | ◎ |
1016 | 多田李衣菜 | ◎ | ◎ | ◎ | ◎ |
1017 | 佐々木千枝 | ◎ | ◎ | ◎ | ◎ |
1018 | 速水奏 | ◎ | ◎ | ◎ | ◎ |
1019 | 日野茜 | ◎ | ◎ | ◎ | ◎ |
1020 | 木村夏樹 | ◎ | ◎ | ◎ | ◎ |
1021 | 三好紗南 | ◎ | ◎ | ◎ | - |
1022 | 安部菜々 | ◎ | ◎ | ◎ | ◎ |
1023 | 高森藍子 | ◎ | ◎ | ◎ | ◎ |
1024 | 北条加蓮 | ◎ | ◎ | ◎ | ◎ |
1025 | 城ヶ崎莉嘉 | ◎ | ◎ | ◎ | ◎ |
1026 | 兵頭レナ | ◎ | ◎ | ◎ | - |
1027 | 高垣楓 | ◎ | ◎ | ◎ | ◎ |
1028 | 輿水幸子 | ◎ | ◎ | ◎ | ◎ |
1029 | 市原仁奈 | ◎ | ◎ | ◎ | ◎ |
1030 | 向井拓海 | ◎ | ◎ | ◎ | ◎ |
1031 | 結城晴 | ◎ | ◎ | ◎ | 実装なし |
1032 | 諸星きらり | ◎ | ◎ | ◎ | ◎ |
1033 | 鷺沢文香 | ◎ | ◎ | ◎ | ◎ |
1034 | 櫻井桃華 | ◎ | ◎ | ◎ | ◎ |
1035 | 橘ありす | ◎ | ◎ | ◎ | ◎ |
1036 | 姫川友紀 | ◎ | ◎ | ◎ | ◎ |
1037 | 佐久間まゆ | ◎ | ◎ | ◎ | ◎ |
1038 | 星輝子 | ◎ | ◎ | ◎ | ◎ |
1039 | 堀裕子 | ◎ | ◎ | ◎ | ◎ |
1040 | 中野有香 | ◎ | ◎ | ◎ | ◎ |
1041 | 塩見周子 | ◎ | ◎ | ◎ | ◎ |
1042 | 相葉夕美 | ◎ | ◎ | ◎ | ◎ |
1043 | 一ノ瀬志希 | ◎ | ◎ | ◎ | ◎ |
1044 | 小早川紗枝 | ◎ | ◎ | ◎ | ◎ |
1045 | 丹羽仁美 | ◎ | ◎ | ◎ | - |
1046 | 十時愛梨 | ◎ | ◎ | ◎ | ◎ |
1047 | 白坂小梅 | ◎ | ◎ | ◎ | ◎ |
1048 | 財前時子 | ◎ | ◎ | ◎ | - |
1049 | 成宮由愛 | ◎ | ◎ | ◎ | - |
1050 | 上田鈴帆 | ◎ | ◎ | ◎ | ◎ |
1051 | 緒方智絵里 | ◎ | ◎ | ◎ | ◎ |
1052 | 佐藤心 | ◎ | ◎ | ◎ | ◎ |
1053 | 神谷奈緒 | ◎ | ◎ | ◎ | ◎ |
1054 | 福山舞 | ◎ | ◎ | ◎ | - |
1055 | 小関麗奈 | ◎ | ◎ | ◎ | 実装なし |
1056 | 工藤忍 | ◎ | ◎ | ◎ | - |
1057 | 喜多見柚 | ◎ | ◎ | ◎ | 実装なし |
1058 | 城ヶ崎美嘉 | ◎ | ◎ | ◎ | ◎ |
1059 | 藤原肇 | ◎ | ◎ | ◎ | 実装なし |
1060 | 森久保乃々 | ◎ | ◎ | ◎ | ◎ |
1061 | 五十嵐響子 | ◎ | ◎ | ◎ | ◎ |
1062 | 道明寺歌鈴 | ◎ | ◎ | ◎ | ◎ |
1063 | アナスタシア | ◎ | ◎ | ◎ | ◎ |
1064 | 池袋晶葉 | ◎ | ◎ | ◎ | - |
1065 | 荒木比奈 | ◎ | ◎ | ◎ | 実装なし? |
1066 | 新田美波 | ◎ | ◎ | ◎ | ◎ |
1067 | ナターリア | ◎ | ◎ | ◎ | 実装なし? |
1068 | 高峯のあ | ◎ | ◎ | ◎ | - |
1069 | 白菊ほたる | ◎ | ◎ | ◎ | 実装なし? |
1070 | 早坂美鈴 | ◎ | ◎ | ◎ | ◎ |
1071 | 浜口あやめ | ◎ | ◎ | ◎ | ◎ |
1072 | 乙倉悠貴 | ◎ | ◎ | ◎ | ◎ |
1073 | 喜多日菜子 | ◎ | ◎ | ◎ | 実装なし |
1074 | ライラ | ◎ | ◎ | ◎ | - |
1075 | 原田美世 | ◎ | ◎ | ◎ | - |
1076 | 和久井留美 | ◎ | ◎ | ◎ | - |
1077 | 村上巴 | ◎ | ◎ | ◎ | 実装なし |
1078 | 八神マキノ | ◎ | ◎ | ◎ | 実装なし? |
1079 | 大原みちる | ◎ | ◎ | ◎ | - |
1080 | 今井加奈 | ◎ | ◎ | ◎ | - |
1081 | 綾瀬穂乃果 | ◎ | ◎ | ◎ | - |
1082 | 岡崎泰葉 | ◎ | ◎ | ◎ | - |
1083 | 桃井あずき | ◎ | ◎ | ◎ | - |
1084 | 横山千佳 | ◎ | ◎ | ◎ | - |
1085 | クラリス | ◎ | ◎ | ◎ | - |
1086 | 黒川千秋 | ◎ | ◎ | ◎ | - |
1087 | 吉岡沙紀 | ◎ | ◎ | ◎ | - |
1088 | ケイト | ◎ | ◎ | ◎ | - |
1089 | 片桐早苗 | ◎ | ◎ | ◎ | ◎ |
1090 | 若林智香 | ◎ | ◎ | ◎ | - |
1091 | キャシー・グラハム | ◎ | ◎ | ◎ | - |
1092 | 双葉杏 | ◎ | ◎ | ◎ | ◎ |
1093 | 三船美優 | ◎ | ◎ | ◎ | ◎ |
1094 | イヴ・サンタクロース | ◎ | ◎ | ◎ | - |
1095 | 桐生つかさ | ◎ | ◎ | ◎ | 実装なし |
1096 | 依田芳乃 | ◎ | ◎ | ◎ | ◎ |
1097 | 関裕美 | ◎ | ◎ | ◎ | 実装なし? |
1098 | 水本ゆかり | ◎ | ◎ | ◎ | ◎ |
1099 | 遊佐こずえ | ◎ | ◎ | ◎ | 実装なし |
1100 | 鷹富士茄子 | ◎ | ◎ | ◎ | 実装なし |
1101 | 古澤頼子 | ◎ | ◎ | ◎ | - |
1102 | 二宮飛鳥 | ◎ | ◎ | ◎ | ◎ |
1103 | 南条光 | ◎ | ◎ | ◎ | 実装なし? |
1104 | 脇山珠美 | ◎ | ◎ | ◎ | ◎ |
1105 | 村松さくら | ◎ | ◎ | ◎ | - |
1106 | 大石泉 | ◎ | ◎ | ◎ | - |
1107 | 土屋亜子 | ◎ | ◎ | ◎ | - |
1108 | 冴島清美 | ◎ | ◎ | ◎ | - |
1109 | 望月聖 | ◎ | ◎ | ◎ | 実装なし |
1110 | 奥山沙織 | ◎ | ◎ | ◎ | - |
1111 | 浅野風香 | ◎ | ◎ | ◎ | - |
1112 | 矢口美羽 | ◎ | ◎ | ◎ | - |
1113 | 難波笑美 | ◎ | ◎ | ◎ | ◎ |
1114 | 大和亜季 | ◎ | ◎ | ◎ | ◎ |
1115 | 佐城雪美 | ◎ | ◎ | ◎ | 実装なし |
1116 | 並木芽衣子 | ◎ | ◎ | ◎ | - |
1117 | 棟方愛海 | ◎ | ◎ | ◎ | 実装なし? |
1118 | 松尾千鶴 | ◎ | ◎ | ◎ | - |
1119 | 松山久美子 | ◎ | ◎ | ◎ | - |
1120 | 長富蓮実 | ◎ | ◎ | ◎ | - |
1121 | 野々村そら | ◎ | ◎ | ◎ | - |
1122 | 赤西瑛梨華 | ◎ | ◎ | ◎ | - |
1123 | 杉坂海 | ◎ | ◎ | ◎ | - |
1124 | 龍崎薫 | ◎ | ◎ | ◎ | ◎ |
1125 | 月宮雅 | ◎ | ◎ | ◎ | - |
1126 | 岸部彩華 | ◎ | ◎ | ◎ | - |
1127 | 衛藤美紗希 | ◎ | ◎ | ◎ | - |
1128 | 藤本里奈 | ◎ | ◎ | ◎ | ◎ |
1129 | 西島櫂 | ◎ | ◎ | ◎ | - |
1130 | ヘレン | ◎ | ◎ | ◎ | - |
1131 | 斉藤洋子 | ◎ | ◎ | ◎ | - |
1132 | 真鍋いつき | ◎ | ◎ | ◎ | - |
1133 | 浅利七海 | ◎ | ◎ | ◎ | 実装なし |
1134 | 松本沙理奈 | ◎ | ◎ | ◎ | - |
1135 | 水木聖來 | ◎ | ◎ | ◎ | - |
1136 | 大沼くるみ | ◎ | ◎ | ◎ | - |
1137 | 安斎都 | ◎ | ◎ | ◎ | - |
1138 | 小松伊吹 | ◎ | ◎ | ◎ | - |
1139 | 梅木音葉 | ◎ | ◎ | ◎ | - |
1140 | 栗原ネネ | ◎ | ◎ | ◎ | - |
1141 | 涼宮星花 | ◎ | ◎ | ◎ | - |
1142 | 及川雫 | ◎ | ◎ | ◎ | ◎ |
1143 | 古賀小春 | ◎ | ◎ | ◎ | - |
1144 | 的場梨沙 | ◎ | ◎ | ◎ | 実装なし |
1145 | 伊集院惠 | ◎ | ◎ | ◎ | - |
1146 | 江上椿 | ◎ | ◎ | ◎ | - |
1147 | 相馬夏美 | ◎ | ◎ | ◎ | - |
1148 | 槙原志保 | ◎ | ◎ | ◎ | - |
1149 | 水野翠 | ◎ | ◎ | ◎ | - |
1150 | 松原早耶 | ◎ | ◎ | ◎ | - |
1151 | 柳清良 | ◎ | ◎ | ◎ | - |
1152 | 日下部若葉 | ◎ | ◎ | ◎ | - |
1153 | 相川千夏 | ◎ | ◎ | ◎ | - |
1154 | 木場真奈美 | ◎ | ◎ | ◎ | - |
1155 | 西川保奈美 | ◎ | ◎ | ◎ | - |
1156 | 愛野渚 | ◎ | ◎ | ◎ | - |
1157 | 仙崎恵磨 | ◎ | ◎ | ◎ | - |
1158 | 首藤葵 | ◎ | ◎ | ◎ | - |
1159 | 日高愛 | ◎ | ◎ | ◎ | ◎ |
1160 | 太田優 | ◎ | ◎ | ◎ | - |
1161 | 東郷あい | ◎ | ◎ | ◎ | - |
1162 | 松永涼 | ◎ | ◎ | ◎ | ◎ |
1163 | 高橋礼子 | ◎ | ◎ | ◎ | - |
1164 | 柊志乃 | ◎ | ◎ | ◎ | - |
1165 | 海老原菜帆 | ◎ | ◎ | ◎ | - |
1166 | 篠原礼 | ◎ | ◎ | ◎ | - |
1167 | 間中美里 | ◎ | ◎ | ◎ | - |
1168 | 大西由里子 | ◎ | ◎ | ◎ | - |
1169 | 小室千奈美 | ◎ | ◎ | ◎ | - |
1170 | 秋月涼 | ◎ | ◎ | ◎ | ◎ |
1171 | 持田亜里沙 | ◎ | ◎ | ◎ | - |
1172 | 有浦柑奈 | ◎ | ◎ | ◎ | - |
1173 | 井村雪菜 | ◎ | ◎ | ◎ | - |
1174 | 氏家むつみ | ◎ | ◎ | ◎ | - |
1175 | 浜川愛結奈 | ◎ | ◎ | ◎ | - |
1176 | 榊原里美 | ◎ | ◎ | ◎ | - |
1177 | 柳瀬美由紀 | ◎ | ◎ | ◎ | - |
1178 | 藤居朋 | ◎ | ◎ | ◎ | - |
1179 | 服部瞳子 | ◎ | ◎ | ◎ | - |
1180 | 沢田麻理菜 | ◎ | ◎ | ◎ | - |
1181 | 水谷絵理 | ◎ | ◎ | ◎ | ◎ |
1182 | 北川真尋 | ◎ | ◎ | ◎ | - |
1183 | 楊菲菲 | ◎ | ◎ | ◎ | - |
1184 | 相原雪乃 | ◎ | ◎ | ◎ | - |
1185 | 桐野アヤ | ◎ | ◎ | ◎ | - |
1186 | 瀬名詩織 | ◎ | ◎ | ◎ | - |
1187 | 辻野あかり | ◎ | ◎ | ◎ | 実装なし |
1188 | 砂塚あきら | ◎ | ◎ | ◎ | 実装なし |
1189 | 夢見りあむ | ◎ | ◎ | ◎ | 実装なし |
1190 | 黒埼ちとせ | ◎ | ◎ | ◎ | ◎ |
1191 | 白雪千夜 | ◎ | ◎ | ◎ | ◎ |
1192 | 久川凪 | ◎ | ◎ | ◎ | ◎ |
1193 | 久川颯 | ◎ | ◎ | ◎ | ◎ |
[C-1]ぷち髪型確認用
- 実行場所
ぷちデレラページなら多分どこでも? - 概要
実行すると、所属ぷちデレラの解放済み髪型一覧が.txt
でDLされます
Excel等にそのまま貼り付けられるかと。
[C-1] ぷち解放済み髪型一覧リストDL
// そのぷちデレラの髪型開放確認APIに連続アタッチして結果をDL
(async()=>{
// ① アタッチ用の連番定義etc一気に作成 from:1 ~to:193
const _fromNum = 1;
const _toNum = 193;
if(_fromNum > _toNum){ return console.error("from-to 番号が不正かも"); }
const _apiUrl = "https://sp.pf.mbga.jp/12008305/?guid=ON&url=http://mobamas.net/idolmaster/petit_cg/ajax_hair_styling_list_by_idol_id";
const _dlTargetDefObj = [];
const _petit_baseId = 1000; // 髪型開放の場合、衣装とは違い 4ケタベースっぽいので注意
// 閉じタグエスケープ対応の為に >記号を利用。ぷち連番を10001~10193(193人分)生成
for(let _n=_fromNum; _toNum>=_n; _n++){
const _dlFileName = `hair_released_list_petit_id_${_petit_baseId+_n}`;
_dlTargetDefObj.push( { "filename" : _dlFileName , "url" : _apiUrl , "optionExt" : ".jsext" , "result_key_name":_petit_baseId+_n ,"PostObject" : { "idol_id" : (_petit_baseId+_n) }} );
}
const _resultMap = new Map();
console.info("================== DL処理を開始します ==================");
function _fileDl(_dlInfo , _index) {
return new Promise((resolve,reject) => {
const _fileName = _dlInfo["filename"];
const _url = _dlInfo["url"];
const _idol_id = _dlInfo["PostObject"]["idol_id"];
setTimeout(async () => {
const _formData = new FormData();
if(_dlInfo["PostObject"]){
const _pObjs = _dlInfo["PostObject"];
for(const _keyName in _pObjs){
const _val = _pObjs[_keyName];
_formData.append( _keyName , _val );
}
}
const _hairData = await fetch(_url,{ method: "POST", mode:"no-cors" , body: _formData })
.then(_res=>{
if(!_res.ok){
throw new Error(_res.statusText);
}else{
try{
// エラーページ自体(html)に繋がれる可能性もあるので、JSONパースエラーも失敗とみなす
const _json = _res.json();
return _json;
}catch(_err){
throw new Error("JSONパース失敗");
}
}
})
.catch(_err=>{
const _resultValArr = [];
_resultValArr.push( "" ); // ぷち名相当
_resultValArr.push( "" ); // 髪型数相当
for(let _n=0; 9>=_n; _n++){ _resultValArr.push("") }
_resultMap.set( _dlInfo["result_key_name"] , _resultValArr);
console.error(`${_idol_id} : DLエラー(未所属判定)`, _err);
});
console.log(_hairData);
// === json 取得成功と判断
if(_hairData){
const _resultValArr = [];
const _hairArr = [];
const _hariList = _hairData["hair_list"];
let _petitName;
for(let _n=0; 9>=_n; _n++){ // 9回回して、10xxx~19xxx まで確認
const _4keta = _n;
let _hairIdHit = false;
_hariList.forEach(_item=>{
const _hairId = _item["hair_id"];
if(_4keta == _hairId[1]){ // 1X??? 4桁の値が合致
const _hairName = _item["hair_name"];
if(!_petitName){ _petitName = _hairName.split(/[+]?の髪型/).shift(); }
const _setFormat = `${_hairId} ${_hairName.replace(_petitName,"")}`;
_hairArr.push( _setFormat ); // 髪型名
_hairIdHit = true;
}
});
if(_hairIdHit == false){
_hairArr.push(""); // 未取得時は空白挿入
}
}
_resultValArr.push( _petitName );
_resultValArr.push( _hariList.length );
_resultValArr.push( ..._hairArr ); // 髪型情報を展開格納
_resultMap.set( _dlInfo["result_key_name"] , _resultValArr );
}
resolve();
}, 100); // DL間隔ミリ秒。あまり縮めないほうが良い
});
}
// 実処理開始
(async () => {
await _dlTargetDefObj.reduce((promise, _dlInfo , _currentIndex) => {
return promise.then(async () => {
await _fileDl(_dlInfo , _currentIndex);
});
}, Promise.resolve());
console.info("=== 予約中のデータを全てDLしたと判断されました ====");
console.info(_resultMap);
{
let _outStr = "ぷちヘアスタイル解放状況一覧\nID / 開放済 /\n※ タブで整形されているので、Excel等にそのまま貼り付けられます\n\n";
_resultMap.forEach((_e , _key)=>{
//_outStr += ( "|\t" + _key + "\t|\t" + _e.join("\t|\t") ) + "\n"; // 自分用 | セパレータ含
_outStr += ( _key + "\t" + _e.join("\t") ) + "\n"; // 一般用
});
console.log(_outStr);
const _dlUrl = URL.createObjectURL( new Blob([_outStr+"\n\n"] , {type: "text/plain"}) );
const _a = document.createElement('a');
_a.href = _dlUrl;
_a.download = `_ぷちヘアスタイル開放状況一覧.txt`;
document.body.appendChild(_a);
_a.click();
document.body.removeChild(_a);
URL.revokeObjectURL(_dlUrl);
}
})();
})();