«前の日記(2014年 04月07日(Mon)) 最新 次の日記(2014年 04月09日(Wed))» 編集

日記のような何か

2002|12|
2003|01|02|03|04|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|08|09|10|11|12|
2020|01|02|03|04|06|07|08|09|10|11|12|
2021|01|02|03|04|05|07|08|10|11|12|
2022|01|

ようこそいらっしゃいました。
あなたは今日人目、合計人目のお客様です(ちなみに昨日は人のお客様がいらっしゃいました)。
よろしければツッコミに足跡等を残していって下さいな。

My status ← skypeやってます。


2014年 04月08日(Tue) [長年日記]

_ [TCG][ruby][プログラム]ブシロードTCG Scraper

以前似たようなプログラムを日記に載せてたけど、古いのでメンテを兼ねて使いやすくしてみた。

プログラムはこんな感じ

  • bushiroad-tcg-scraper.rb
#coding: utf-8

require 'thor'
require 'mechanize'
require 'watir-webdriver'
require 'yaml'

#
#= ブシロード製TCGのカードリストをスクレイピングしてYAMLデータを出力するツール
#
#Authors::   ねくろん(@necron)
#Version::   1.0 2014-04-07 necron
#Copyright:: Copyright (C) necron-web.com, 2014. All rights reserved.
#
module BushiroadTCGScraper
  class CLI < Thor
    #
    #=== エキスパンションのリストを取得する
    #
    #入力:: config.yml
    #       proxy: [proxy, port]
    #       uri: カードリストのURI  (例: http://ws-tcg.com/jsp/cardlist)
    #
    #出力:: expansion_list.yml
    #       text: エキスパンション名
    #       onclick: (同名エキスパンション対策用データ)
    #
    desc "get_expansion_list", "エキスパンションのリストを取得する"
    def get_expansion_list
      config = YAML.load_file("config.yml")

      list = []

      agent = Mechanize.new
      agent.set_proxy(*config["proxy"]) if config["proxy"]
      puts "connecting #{config["uri"]} ..."
      page = agent.get(config["uri"])

      (page/"div[@id='expansionList'] a").to_a.each do |link|
        puts text = link.inner_text.strip
        list << {"text" => text, "onclick" => link["onclick"]}
      end

      File.open("expansion_list.yml", "w") do |file|
        file << YAML.dump(list)
      end
    end

    #
    #=== エクスパンションリストからカードのリンクリストを取得する
    #
    #入力:: config.yml
    #       expansion_list.yml
    #
    #出力:: card_link_list.yml
    #       エキスパンション名: [個々のカードのURI,...]
    #
    desc "get_card_link_list",
      "エクスパンションリストからカードのリンクリストを取得する"
    def get_card_link_list
      config = YAML.load_file("config.yml")
      expansion_list = YAML.load_file("expansion_list.yml")

      puts "connecting #{config["uri"]} ..."
      browser = Watir::Browser.new
      browser.goto config["uri"]

      list = {}
      title = nil

      begin
        expansion_list.each do |expansion|
          title = expansion["text"]
          link = nil

          browser.links.each do |i|
            link = i if i.onclick == "#{expansion["onclick"]}"
          end

          link.click

          array = []
          n = 0

          begin
            sleep 1
            flag = false
            browser.links.each do |i|
              if i.href =~ /cardno/
                array << i.href
                puts i.href
              end
              if i.text == '≫'
                flag = true
              end
            end
            browser.link(:text, '≫').click if flag
          end while flag

          list[title] = array
        end
      ensure
        browser.close

        File.open("card_link_list.yml", 'w') do |file|
          file << YAML.dump(list)
        end
      end
    end

    #
    #=== カードのリンクリストから個々のカード情報を取得する
    #
    #入力:: config.yml
    #       card_link_list.yml
    #
    #出力:: card_list.yml
    #
    desc "get_card", "カードのリンクリストから個々のカード情報を取得する"
    def get_card
      config = YAML.load_file("config.yml")
      card_link_list = YAML.load_file("card_link_list.yml")

      agent = Mechanize.new
      agent.set_proxy(*config["proxy"]) if config["proxy"]

      output = {}

      card_link_list.each do |expansion, link_list|

        list = []

        link_list.each do |card_uri|
          puts "connecting #{card_uri} ..."
          page = agent.get card_uri

          array = (page/'table.status td').to_a.inject([]) do |array, e|
            array << e.inner_html
          end

          card = {}

          if config["format"]
            config["format"].each do |i|
              card[i["key"]] = if i["regexp"].to_s.empty?
                array[i["line"]]
              else
                Regexp.new(i["regexp"]).match(array[i["line"]]).to_a[1]
              end
            end
          else
            card["debug"] = array
          end

          list << card
        end

        output[expansion] = list
      end

      File.open("card_list.yml", 'w') do |file|
        file << YAML.dump(output)
      end
    end
  end
end

module Watir
  class Anchor
    attributes(:string => [:'onclick'])
  end
end

BushiroadTCGScraper::CLI.start(ARGV)

使い方。

まずrubyがインストールされてることが大前提。あとFirefoxブラウザが必要。 他のブラウザ使う場合は各自でプログラムを修正しよう。 一応 ruby2.0.0-p195 で動作確認している。

あと、MechanizeとWatirとThorが必要なので、

gem install Mechanize
gem install Watir
gem install Thor

とかしておこう。

1. config.ymlの用意 configファイルに

---
uri: http://ws-tcg.com/jsp/cardlist

のようにブシロードのカードリストがあるURIを記載する。proxyが必要な人は下記のようにIPとportを指定可能。必要なければ書く必要はない。

proxy:
  - 128.0.0.1
  - 8080

2. get_expansion_listを実行

ruby ./bushiroad-tcg-scraper.rb get_expansion_list

とコマンドラインを打ち込んで実行。するとexpansion_list.ymlという中間ファイルが出力される。

中身はこんな感じ

---
- text: D.C. D.C.II
  onclick: showExpansionDetail('1',''); return false;
- text: リトルバスターズ!
  onclick: showExpansionDetail('2',''); return false;
- text: ゼロの使い魔
  onclick: showExpansionDetail('3',''); return false;
- text: なのはStrikerS
  onclick: showExpansionDetail('6',''); return false;
(以下略)

textがエキスパンションの名前。onclickは同名エキスパンションを区別するためのメタ情報。

3. get_card_link_listを実行

ruby ./bushiroad-tcg-scraper.rb get_card_link_list

とコマンドラインを打ち込んで実行。すると勝手にFirefoxブラウザが起動して、エキスパンション毎に個々のカードのリンクリスト(card_link_list.yml)を作成してくれる。

……のだけど、相当時間かかるので注意。expansion_list.ymlの中身を修正して、欲しいエキスパンションだけとかにした方が良いかも。

例えばexpansion_list.ymlの中身を修正して以下のようにしたら、

---
- text: なのはStrikerS
  onclick: showExpansionDetail('6',''); return false;

結果はこうなる。

---
なのはStrikerS:
- http://ws-tcg.com/jsp/cardlist?cardno=NS/W04-001
- http://ws-tcg.com/jsp/cardlist?cardno=NS/W04-001S
- http://ws-tcg.com/jsp/cardlist?cardno=NS/W04-002
- http://ws-tcg.com/jsp/cardlist?cardno=NS/W04-002S
- http://ws-tcg.com/jsp/cardlist?cardno=NS/W04-003
(以下略)

4.get_cardを実行して取得されるカードのデータを確認する。

カードのリンクリストができたら後はget_cardを実行して終了。

……だったら良いんだけど、そう簡単ではない。このツールはブシロードのTCG汎用として作っているので、取得したいカードゲーム毎にそれに合わせたパラメータファイルを作ってやらないといけない。

パラメータはconfig.ymlにformatというキーで指定するんだけど、config.ymlにformatキーが記述されていない場合、Webページに表示されているデータをそのまま取ってくるようになっている。

例えば、card_link_list.ymlを編集して

---
なのはStrikerS:
- http://ws-tcg.com/jsp/cardlist?cardno=NS/W04-001

以下のように実行してみると、

ruby ./bushiroad-tcg-scraper.rb get_card

結果のcard_list.ymlファイルの中身はこうなる。

---

なのはStrikerS:
- debug:
  - <img src="../cardlist/cardimages/ns_w04_001.gif" alt="カード"><br><a href="javascript:void(0);"
    onclick="showQuestion('NS/W04-001'); return false;">≫ このカードに関するQ&amp;A</a>
  - "\r\nキャロ・ル・ルシエ<br><span class=\"kana\">キャロルルシエ</span>\r\n"
  - NS/W04-001
  - RR
  - なのはStrikerS
  - "\r\n<img src=\"/cardlist/partimages/w.gif\">"
  - キャラ
  - <img src="../cardlist/partimages/yellow.gif">
  - '1'
  - '1'
  - '5000'
  - <img src="../cardlist/partimages/soul.gif">
  - <img src="../cardlist/partimages/soul.gif">
  - "\r\n魔法 ・ 竜\r\n"
  - 【自】 このカードがアタックした時、あなたは自分の舞台にいる「エリオ・モンディアル」を1枚選び、手札に戻す。<br>【自】 アンコール [手札のキャラを1枚控え室に置く]
    (このカードが舞台から控え室に置かれた時、あなたはコストを払ってよい。そうしたら、このカードがいた枠に【レスト】して置く)<br>
  - 若き槍騎士に駆け抜ける力を!<br>

5. config.ymlにformatキーを追加する。 上の結果を見ながらformatキーを作成する。WSの場合はこんな感じ(もちろんUTF-8で書くように)。

format:
  - key: カード画像
    line: 0
    regexp: <img src="../cardlist/cardimages/(.+\.gif)"
  - key: カード名
    line: 1
    regexp: \s*(.+)<br><span class="kana">.*</span>
  - key: カード名(カナ)
    line: 1
    regexp: .+<br><span class="kana">(.*)</span>
  - key: カード番号
    line: 2
    regexp:
  - key: レアリティ
    line: 3
    regexp:
  - key: エクスパンション
    line: 4
    regexp:
  - key: サイド
    line: 5
    regexp: \s*(.+)
  - key: 種類
    line: 6
    regexp:
  - key: 色
    line: 7
    regexp:
  - key: レベル
    line: 8
    regexp:
  - key: コスト
    line: 9
    regexp:
  - key: パワー
    line: 10
    regexp:
  - key: ソウル
    line: 11
    regexp:
  - key: トリガー
    line: 12
    regexp:
  - key: 特徴
    line: 13
    regexp: \s*(.+)\s\s
  - key: テキスト
    line: 14
    regexp:
  - key: フレーバー
    line: 15
    regexp:

regexpに正規表現を記述し、取り出したい部分を()で囲む。一行全部取り出す場合はregexpは何も書かなくて構わない。

6. 再度get_cardでカードデータを取得する。 実際に上の記述をconfig.ymlに追加して、get_cardを実行すると、

---
なのはStrikerS:
- カード画像: ns_w04_001.gif
  カード名: キャロ・ル・ルシエ
  カード名(カナ): キャロルルシエ
  カード番号: NS/W04-001
  レアリティ: RR
  エクスパンション: なのはStrikerS
  サイド: <img src="/cardlist/partimages/w.gif">
  種類: キャラ
  色: <img src="../cardlist/partimages/yellow.gif">
  レベル: '1'
  コスト: '1'
  パワー: '5000'
  ソウル: <img src="../cardlist/partimages/soul.gif">
  トリガー: <img src="../cardlist/partimages/soul.gif">
  特徴: 魔法 ・ 竜
  テキスト: 【自】 このカードがアタックした時、あなたは自分の舞台にいる「エリオ・モンディアル」を1枚選び、手札に戻す。<br>【自】 アンコール [手札のキャラを1枚控え室に置く]
    (このカードが舞台から控え室に置かれた時、あなたはコストを払ってよい。そうしたら、このカードがいた枠に【レスト】して置く)<br>
  フレーバー: 若き槍騎士に駆け抜ける力を!<br>

こんな内容のYAMLが出力される。後はエクセルに変換するなり、Javascriptで使うなりご自由に。


Googleカスタム検索

my recommend books