2ch まとめブログで注目されている商品を解析する

ここ数日のまとめ的な記事.先週末に Amazon 関連の情報をいろいろ調べて 2ch まとめブログで注目されている商品を解析するスクリプトを書いてみました.

前書き

ここ2, 3日,AmazonAPI を叩いていろいろ実験をしていた訳ですが,その(最終的な)目的はまぁご想像の通りです.この手の話題は何と言うかなかなか直球では言及しにくいのと,Web 上で収入を得ると言う手段は個人レベルでやっている(資本や自分のリソースをあまり突っ込めない)限りはなかなかメインにするには難しいのとで,これまでほとんどスルー状態でした.ただ,一方で,何かあった時のために(収入の)選択肢は増やしておきたいと言う思いも常にありました.

Web ページ上で公開したコンテンツに広告を貼って収入を得ると言うスタイルの場合,問題となるのは以下の 2点となります.

  • 多くの人に興味を持ってもらえるような(できれば釣りではない)コンテンツを作成する.
  • コンテンツを閲覧しに来た人がクリックしたくなるような広告を配置する.

1点目は永遠の課題と言うか,「これ」と言う答えの出る類のものではないので,自分の得意な分野のコンテンツをできるだけ高品質で提供するように心がけると言う事で,ここ数日は 2点目の問題を考えていました.

例えば,Web 上での広告として有名なものとして Google AdSense がありますが,自分の(読者としての)経験上,広告と言う点を考慮しないとしても,多くの場合はクリックする気がおきないと言う問題があります.これに対して,Amazon の商品情報は(それがアソシエイトリンクだと分かっていても)少なくともクリック位はしたくなる機会がぽつぽつあります.クリック報酬と成果報酬の差があるので単純には比較できないのですが,実感としても,広告としては Amazon の方が魅力的であると言う気がします.

ただ,Amazon の商品情報も Amazon 自体から提供されている標準のウィジェット(ランダムに商品を表示してくれるもの)は魅力に乏しいと言う印象があります.そのせいもあって,一時期,自分で商品を選んで掲載すると言う方法を取ってみたのですが,ページ数が増えるにつれて手動による更新には無理がある,また,そもそも何を紹介して良いのか分からないと言う問題で詰んだと言う経験もあります.

Amazon の商品情報と言うと,2ch まとめブログ系の Web サイトで Amazon 商品情報を掲載しているのをよく見かけます.さらに,「この商品,他(の 2ch まとめブログ)でも見たな」と言う感想を抱くことも結構ありました.あの辺りのサイトは,趣味の枠を超えて運営されているのではと感じられるものもそれなりに存在するので,そう言った「何を紹介するか」に関してもよく研究しているのだろうと予想されます.

なので,どんなものを紹介したら良いのか 2ch まとめブログから抽出したデータを参考に,少し真面目に考えてみようと言う結論に至りました.

2ch まとめブログで注目されている商品を解析するスクリプト

そう言った経緯で作ったのが最初の記事.http://cielquis.net/amazon/index.html は,まず http://cielquis.net/link.html の「2ch まとめブログ」に列挙されてある URL からページ情報を取得し,その中に記載されてある ASIN コードを抽出します.そして,各種 ASIN コードがいくつのサイトで紹介されていたのかをカウントし,紹介数の多いものから順に掲載しています.

最初に記述している対象にしたサイト数は,先のリンク先に掲載されている 2ch まとめブログ系の URL から「1件でも ASIN コードを取得できた Web サイト」の数を表しています.リストを作成するのに使用したスクリプトは以下のような感じです.

#!/bin/ruby -Ku
require 'open-uri'
require 'rubygems'
require 'crown'

# --------------------------------------------------------------------------- #
#  settings
# --------------------------------------------------------------------------- #
THRESHOLD = 3

# --------------------------------------------------------------------------- #
#  settings for Amazon::Ecs
# --------------------------------------------------------------------------- #
Amazon::Ecs.options = {
    :aWS_access_key_id  => 'YourAccessKey',
    :aWS_secret_key     => 'YourSecretKey',
    :country            => :jp,
}

# --------------------------------------------------------------------------- #
#  get_urilist
# --------------------------------------------------------------------------- #
def get_urilist(uri)
    begin
        results = Array.new
        open(uri) { |f|
            html = Nokogiri::HTML.parse(f.read)
            elements = html.search("ul#ni-chan/li/a")
            break if (elements == nil || elements.length == 0)
            
            elements.each { |node|
                next if (node['href'] == nil)
                
                link = node['href'].strip
                parser = nil
                begin
                    parser = URI.parse(link)
                rescue URI::InvalidURIError
                    parser = URI.parse(URI.encode(link))
                end
                next if (parser == nil || parser.host == nil || parser.path == nil)
                results.push(link)
            }
        }
        return results
    rescue Exception
        return nil
    end
end

# --------------------------------------------------------------------------- #
#  main
# --------------------------------------------------------------------------- #
begin
    raise "usage amazhack.rb outfile" if (ARGV.length < 1)
    
    v = get_urilist('http://cielquis.net/link.html')
    exit if (v == nil || v.length == 0)
    
    count = 0
    asins = Hash.new
    extractor = Crown::Amazon::AsinExtractor.new
    v.each { |uri|
        puts("getting from #{uri}")
        begin
            tmp = extractor.get(uri)
            count += 1 if (tmp.length > 0)
            tmp.each { |asin|
                if (asins.include?(asin))
                    asins[asin] += 1
                else
                    asins[asin] = 1
                end
            }
        rescue Exception
            next
        end
    }
    
    puts("get #{asins.length} ASINs from #{count} Web sites")
    File.open(ARGV[0], 'w') { |file|
        file.puts("# get #{asins.length} ASINs from #{count} Web sites")
        file.puts("# ASIN,Count,Total,\"Title\",Price,Date,\"Image URL\"")
        asins.to_a.sort { |x, y| y[1] <=> x[1] }.each { |key, value|
            break if (value < THRESHOLD)
            puts("getting amazon info for #{key}")
            result = ::Amazon::Ecs.item_lookup(key, { :response_group => 'Medium' })
            next if (result == nil || result.items.length == 0)
            item = result.first_item
            file.printf("%s,%d,%d,\"%s\",%s,%s,\"%s\"\n",
                item.get('asin'), value, count,
                item.get('title'), item.get('amount'),
                item.get('releasedate'), item.get('largeimage/url'))
        }
    }
rescue Exception => e
    $stderr.puts(e.message)
end

まだまだ何かを言えるような検討は行っていないので,取りあえず作成するところまで.実際に Web 上でどこまでやって行くのかは不透明なのですが,いざと言う時の事も考えて,いろいろ解析だけはしておこうかなと思います.