アバターリスト
実は私は「VRCで使える有償アバター一覧」というGoogleスプレッドシートを公開して、現在販売されているアバターをそこにまとめています。
もちろんすべてのアバターを網羅できている訳ではないですけど、BOOTHを中心にまとめた結果現在では100体を超えていますので、それなりのデータは用意できているのではと思います(共同編集してくださる方にも、この場を借りてお礼申し上げます)。
VRCで使える有償アバターリストに、試験的にサムネイルを追加しました。リストをそのまま貼り付けるとあまりにも縦長になるので、とりあえずサムネだけ抜き出したものを画像にしときます。https://t.co/ENXUzGLGND pic.twitter.com/jk56lernzw
— Hibit (@hibit_at) 2018年9月28日
人力の限界
ただ、100体を超えてくるとさすがに縦長のデータを見せられてもなんのこっちゃという感が強くなってくると思うので、サムネイルをつけようと思いました。サムネイルはBOOTHの販売ページにありますが、それを人力でコピーして……とやるのは非現実的です。他にも色々入力・保守で大変なことがありまして、人力の限界を感じつつあるこの頃です。
ここはGoogleAppsScriptと正規表現に頑張ってもらいましょう。
一部引用の明記
本記事を書くにあたっては、[GAS] Webスクレイピングで価格comから最安値を取得するを参考にさせていただき、コードの大本も流用させていただきました。ありがとうございます。
ソースコード
とりあえずソース見せろという方へ。
function myFunction() {
var aBook = SpreadsheetApp.getActiveSpreadsheet();
var aSheet = aBook.getSheetByName("test")
var lastRow = aSheet.getDataRange().getLastRow();
for (var i = 2; i <= lastRow; i++) {
var url = aSheet.getRange(i, 1).getValue();
var response = UrlFetchApp.fetch(url);
var html = response.getContentText('utf-8');
var regex = new RegExp("title\>(.*?)\-");
var avatarname = html.match(regex)[1];
var regex = new RegExp("\- (.*?)BOOTH");
var shopname = html.match(regex)[1];
var regex = new RegExp('image" content="(.*?)"');
var imagename = html.match(regex)[1];
aSheet.getRange(i, 2).setValue(avatarname);
aSheet.getRange(i, 3).setValue(shopname);
aSheet.getRange(i, 4).setValue('=Image("' + imagename + '",2)');
}
}
導入
念のため、導入を補足。「ツール」の「スクリプトエディタ」を選択するとエディタが出てきます。ExcelのVBAみたいですね。
URLからソースを取得
データ取得用のシートを別に用意して、その1列目にURLを列挙していきます。リンクが切れていたり、BOOTH以外のページだったりするとプログラムが止まってしまうので、そういった調整もしておきます。
var url = aSheet.getRange(i, 1).getValue();
var response = UrlFetchApp.fetch(url);
var html = response.getContentText('utf-8');
1列目にあるデータをurl
として取得して、更にそのソースをhtml
として取得します。なお、元コードではエンコードは'SHIFT-JIS'
でしたが、'utf-8'
にしないと文字化けするので今回はそうしています。
正規表現でデータを取得
BOOTHのソース
にある黄色の箇所が抽出したい情報です。(とりあえず一番最初に登録したアヌビスちゃんのソースを使わせていただきました。takewakaさんごめん! こんなにかわいいアヌビスちゃんがなんと2,500円! 買うしかない!)
これを以下の正規表現で抽出します。
var regex = new RegExp("title\>(.*?)\-");
var avatarname = html.match(regex)[1];
var regex = new RegExp("\- (.*?)BOOTH");
var shopname = html.match(regex)[1];
var regex = new RegExp('image" content="(.*?)"');
var imagename = html.match(regex)[1];
avatarname
はアバターの名前です。タイトルタグで囲まれており、ハイフンで区切られているので、
「title>」 ~(任意の文字列)~ 「-」
の正規表現で抽出します。なお、(.*)
ではなく(.*?)
にしているのは最短一致にするためです(最初わからなくてハマった)。
shopname
はサークルの名前です。「-」と「-」で囲まれているので、一番始めに一致するのはサークルの名前になるはず……だったのですが、なんとBOOTHのタイトルタグには「サークル名がつかない場合がある」という謎の仕様があるので、これだとマッチせずにエラーを吐いてしまうことが発覚しました。なので、苦し紛れの策として、
「-」 ~(任意の文字列)~「BOOTH」
の正規表現で抽出します。余計なハイフンがついてしまう例もあります(というかそれがほとんどです)が、エラーなしで抽出するにはこれしかなかったんや……。
imagename
はサムネのパスです。ソースコードでは「image" content="サムネのアドレス"」という文字列になっているので、
「image" content="」 ~(任意の文字列)~ 「"」
の正規表現で抽出します。絶対にもっとエレガントなregexがある気がしますが、動けばいいんだよ動けば。
ちなみに抽出しといて何ですが、avatarnameとshopnameは余計なタグがついてたりshopnameが抜けていたりするので使いません。ていうか、今まで人力でまとめてたアバター名(よりわかりやすい)があるし。今後、アバターの名前をまとめるのすら人力では億劫になってきたらもっと工夫するかもしれません。
サムネをシートに貼り付け
後は抽出したサムネをシートにはりつければOKです。Googleスプレッドシートには「=image("画像のパス",引数)」で画像をシートにはりつけられる便利な関数があるので、それを使います。ソースだと
aSheet.getRange(i, 4).setValue('=Image("' + imagename + '",2)');
の部分ですね。第2引数の2は、セルのサイズにサムネを合わせるようにするやつです。こうしてサムネ画像の列ができた後で、元の表に導入したのが以下のようなもの。
BOOTH以外のやつどうするんだとか色々ありましたけど、とりあえずこれでまたしばらくは戦えそうです。
最後に
リストですが、漏れが多いです。モデルの販売が多いというのもありますが、私一人では限界があります。誰でも編集可能にしているので協力プリーズ! URLを入れてくれるだけでいいから! 後はいい感じに処理する仕組みを考えるから!