nekoTheShadow’s diary

IT業界の片隅でひっそり生きるシステムエンジニアです(´・ω・`)

おととい修正ふたたび。

昨日は昨日から見ておとといの修正をしましたが、今日は今日から見ておとといの記事の修正をします。
よくよく確かめてから書かないからこういうことになるんだ。

おとといのことですが、次のような記事を書き、

次のようなコードを張り付けました。(なお現物はこちら)

実のところ、このコードにも間違いというか、誤解を招きかねない部分がありましたので、訂正いたします。

def video_id2user(video_id)
  res = httpGet("http://ext.nicovideo.jp/api/getthumbinfo/#{video_id}")
  xml = REXML::Document.new(res)
  user_id = xml.root.elements["thumb/user_id"].text
  user_nickname = xml.root.elements["thumb/user_nickname"].text
  return {user_id: user_id, user_nickname: user_nickname}
end

以上はvideo_idからuser_idとuser_nicknameを取得するメソッドになりますが、ここに重大なミスがあります。
ここで想定されているのは次のようなxmlです。
なおurlはこちら

つまり、このxmlから以下の部分を抜き出しているわけですね。

<user_id>33089425</user_id>
<user_nickname>きゆみやま</user_nickname>

では別の事例を見てみましょう。(現物はこちら)

もうお分かりのことだと思いますが、このxmlではuser_idとuser_nicknameにあたる部分が次のようになっております。

<ch_id>2598091</ch_id>
<ch_name>仕掛人チャンネル</ch_name>

したがって、次のようなrubyのコードでは妙なことが起きてしまいかねないのですね。

user_id = xml.root.elements["thumb/user_id"].text
user_nickname = xml.root.elements["thumb/user_nickname"].text

なぜなら、user_idやuser_nicknameが存在しないから。


実はニコニコ動画の動画idにはいくつか種類があるようで、無差別に動画idを取得する場合にはそれに配慮する必要があるようなのです。
これに気づくまで、"sm?????"という形ばかりだと思っていました。
実際、上記の例は"so?????"ですね。

ということで、修正後は以下のようになります。

def video_id2user(cmsid)
  res = httpGet("http://ext.nicovideo.jp/api/getthumbinfo/#{video_id}")
  xml = REXML::Document.new(res)

  user_id = user_nickname = String.new
  xml.root.elements["thumb"].each do |line|
    next if line.node_type != :element
    user_id = line.text if line.name.include?("id")
    user_nickname = line.text if line.name.include?("name")
  end
  
  return {user_id: user_id.to_i, user_nickname: user_nickname}
end

変わったのは以下の部分ですね。

user_id = user_nickname = String.new
xml.root.elements["thumb"].each do |line|
  next if line.node_type != :element
  user_id = line.text if line.name.include?("id")
  user_nickname = line.text if line.name.include?("name")
end

具体的に何をやっているのかというと、

  • xmlを一文一文に切り分けて
  • 要素を持つ部分とそうでない部分に分ける
    • 要素を持っていなければ次の一文へ
  • 前者に対して要素を取り出し、"id"ないし"name"を含んでいるかどうかを判定
    • idを含んでいれば変数user_idへ、nameを含んでいればuser_nicknameへそれぞれ格納

という手順になります。
やっていることは単純ですが、基本的にこれですべての動画idに対応できるはずです。
何例か調べてみましたが、大丈夫だと思います。そう信じています。

昨日に引き続き、ミスばかりで申し訳ありません。
今度からはきちんとアイディアを寝かせてから投稿したいと思います。反省。