Amazonからランキングデータを取得してグラフ化するツール
authorj8takagi <j8takagi@nifty.com>
Fri, 26 Oct 2012 13:25:42 +0000 (22:25 +0900)
committerj8takagi <j8takagi@nifty.com>
Fri, 26 Oct 2012 13:25:42 +0000 (22:25 +0900)
ISBN.txt [new file with mode: 0644]
bookdesc.rb [new file with mode: 0644]
bookrank.rb [new file with mode: 0755]
bookrank_batch.rb [new file with mode: 0755]
makehtml.rb [new file with mode: 0644]
makehtmlr.rb [new file with mode: 0644]
makeindex.rb [new file with mode: 0644]
plot.R [new file with mode: 0644]
plot_batch.rb [new file with mode: 0755]

diff --git a/ISBN.txt b/ISBN.txt
new file mode 100644 (file)
index 0000000..728ec03
--- /dev/null
+++ b/ISBN.txt
@@ -0,0 +1,50 @@
+475981339X
+4004150930
+4140807431
+4774141291
+4860650530
+4864010048
+4864010056
+4492521453
+453231139X
+4004308569
+4797336617
+4797357401
+4903506002
+4000062441
+4652078404
+4756107850
+4274067572
+4022502797
+4062573679
+400500475X
+4314009977
+4005004830
+4822283801
+4887596995
+4150503583
+400007489X
+4062577240
+450154970X
+4000253549
+448601863X
+4621045938
+4797341378
+4905849152
+4812445620
+419891477X
+4198914915
+4198915113
+4022645547
+4022645555
+4990491106
+4839938830
+4334035604
+4532191769
+4303714305
+4871483517
+4320026926
+4756136494
+4535600120
+B005IHLNOC
+B005HTNHO0
diff --git a/bookdesc.rb b/bookdesc.rb
new file mode 100644 (file)
index 0000000..ddbe377
--- /dev/null
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+require 'amazon/aws/search'
+include Amazon::AWS
+include Amazon::AWS::Search
+
+class File
+  def bookdesc(isbn)
+    look = ItemLookup.new( 'ASIN', { 'ItemId' => isbn } )
+    look.response_group = ResponseGroup.new( 'Small' )
+    req  = Search::Request.new
+    res = req.search(look)
+    attr = res.item_lookup_response.items.item.item_attributes
+    print attr.author, "『", attr.title, "』(", attr.manufacturer, ")"
+  end
+end
diff --git a/bookrank.rb b/bookrank.rb
new file mode 100755 (executable)
index 0000000..06fb24c
--- /dev/null
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+require 'amazon/aws/search'
+include Amazon::AWS
+workdir = File.expand_path("~/amazonrank")
+
+begin
+  il = ItemLookup.new( 'ASIN', { 'ItemId' => ARGV[0] } )
+  request  = Search::Request.new
+  time  = Time.now.strftime("%Y/%m/%d %H:%M:%S")
+  req = request.search il
+  rank = req.item_lookup_response.items.item.sales_rank
+  raise "ランキングを取得できませんでした。原因不明" if req.nil?
+  csvfile = File.expand_path(workdir.dup << "/" << ARGV[0].dup <<  ".csv")
+  open(csvfile, "a") { |f|
+    f.print ARGV[0], ",", time, ",", req, "\n"
+  }
+rescue => exc
+  STDERR.puts exc
+  errfile = File.expand_path(workdir.dup << "/error.log")
+  open(errfile, "a") { |f|
+    f.print "エラー: ", exc, "\n"
+    f.print "ASBN: ", ARGV[0], "\n"
+    f.print "日時: ", time, "\n"
+    f.print "\n"
+  }
+end
diff --git a/bookrank_batch.rb b/bookrank_batch.rb
new file mode 100755 (executable)
index 0000000..1b8de8b
--- /dev/null
@@ -0,0 +1,22 @@
+#!/usr/local/bin/ruby
+# -*- coding: utf-8 -*-
+require 'amazon/aws/search'
+include Amazon::AWS
+
+workdir = File.expand_path("~/amazonrank")
+isbnfile = File.expand_path(workdir.dup << "/ISBN.txt")
+
+open(isbnfile, "r") { |lines|
+  while isbn = lines.gets
+    isbn = isbn.chomp
+    csvfile = File.expand_path(workdir.dup << "/" << isbn.dup <<  ".csv")
+    il = ItemLookup.new( 'ASIN', { 'ItemId' => isbn } )
+    request  = Search::Request.new
+    time  = Time.now
+    req = request.search il
+    open(csvfile, "a") { |f|
+      f.print isbn, ",", time.strftime("%Y/%m/%d %H:%M:%S"), ",", req.item_lookup_response.items.item.sales_rank, "\n"
+    }
+    sleep 0.5
+  end
+}
diff --git a/makehtml.rb b/makehtml.rb
new file mode 100644 (file)
index 0000000..a5d0ab0
--- /dev/null
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+require './bookdesc'
+
+workdir = "~/amazonrank"
+htmlfile = workdir.dup << "/" << ARGV[0].dup <<  ".html"
+
+open(htmlfile, "w") { |f|
+  f.print <<EOS
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
+<head>
+<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
+EOS
+  f.print "<title>Amazonランキング - ", ARGV[0], "</title>\n"
+
+  f.print <<EOS
+</head>
+<body>
+EOS
+
+  f.print "<h1>Amazonランキング - ASBN", ARGV[0], "</h1>"
+  f.print "<p>"
+  f.bookdesc(ARGV[0])
+  f.print "</p>\n"
+  f.print "<p><a href=\"http://www.amazon.co.jp/dp/", ARGV[0], "\">Amazonのページ</a></p>\n"
+  f.print "<p><a href=\"", ARGV[0], ".csv\">データファイル(CSV形式)</a></p>\n"
+  f.print "<p><a href=\"", ARGV[0], "r.html\">グラフの上下を逆にする</a></p>\n"
+
+  f.print <<EOS
+<p><a href=\"index.html\">目次へ戻る</a></p>
+<div>
+EOS
+
+  f.print "<object data=\"", ARGV[0], ".svg\" type=\"image/svg+xml\" width=\"772.70\" height=\"578.16\">\n"
+  f.print "<img src=\"", ARGV[0], ".png\" alt=\"", ARGV[0], "のランキング\" />\n"
+
+  f.print <<EOS
+</object>
+</div>
+</body>
+</html>
+EOS
+}
diff --git a/makehtmlr.rb b/makehtmlr.rb
new file mode 100644 (file)
index 0000000..1e9cff2
--- /dev/null
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+require './bookdesc'
+
+workdir = "~/amazonrank"
+htmlfile = workdir.dup << "/" << ARGV[0].dup <<  "r.html"
+
+open(htmlfile, "w") { |f|
+  f.print <<EOS
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
+<head>
+<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
+EOS
+  f.print "<title>Amazonランキング - ", ARGV[0], "</title>\n"
+
+  f.print <<EOS
+</head>
+<body>
+EOS
+
+  f.print "<h1>Amazonランキング - ASBN", ARGV[0], "</h1>"
+  f.print "<p>"
+  f.bookdesc(ARGV[0])
+  f.print "</p>\n"
+  f.print "<p><a href=\"http://www.amazon.co.jp/dp/", ARGV[0], "\">Amazonのページ</a></p>\n"
+  f.print "<p><a href=\"", ARGV[0], ".csv\">データファイル(CSV形式)</a></p>\n"
+  f.print "<p><a href=\"", ARGV[0], ".html\">グラフの上下を逆にする</a></p>\n"
+  f.print <<EOS
+<p><a href=\"index.html\">目次へ戻る</a></p>
+<div>
+EOS
+
+  f.print "<object data=\"", ARGV[0], "r.svg\" type=\"image/svg+xml\" width=\"772.70\" height=\"578.16\">\n"
+  f.print "<img src=\"", ARGV[0], "r.png\" alt=\"ASBN", ARGV[0], "のランキング\" />\n"
+
+  f.print <<EOS
+</object>
+</div>
+</body>
+</html>
+EOS
+}
diff --git a/makeindex.rb b/makeindex.rb
new file mode 100644 (file)
index 0000000..431055c
--- /dev/null
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+require './bookdesc'
+
+workdir = "~/amazonrank"
+htmlfile = workdir.dup << "/index.html"
+isbnfile = "ISBN.txt"
+
+open(htmlfile, "w") { |f|
+  f.print <<EOS
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
+<head>
+<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
+<title>Amazonランキング</title>
+</head>
+
+<body>
+<h1>Amazonランキング</h1>
+<ul>
+EOS
+
+  open(isbnfile, "r") { |lines|
+    while l = lines.gets
+      l = l.chomp
+      f.print "<li><a href=\"", l, ".html\">"
+      f.bookdesc(l)
+      f.print "</a> <a href=\"http://www.amazon.co.jp/dp/", l, "\">Amazon</a></li>\n"
+    end
+  }
+  f.print <<EOS
+</ul>
+</body>
+</html>
+EOS
+}
diff --git a/plot.R b/plot.R
new file mode 100644 (file)
index 0000000..9459263
--- /dev/null
+++ b/plot.R
@@ -0,0 +1,56 @@
+library(RSvgDevice)
+
+plotrank <- function(datafile, outfiletype, topup=TRUE)
+{
+    df <- read.table(datafile, sep=",")
+    x <- strptime(df$V2, "%Y/%m/%d %H:%M:%S")
+    y <- df$V3
+    # 数値の大きい方を上にするか、小さい方を上にするかを指定
+    if (topup) {
+      yl = c(ylimmax(max(y, na.rm=TRUE)), 1)
+    } else {
+      yl = c(1, ylimmax(max(y, na.rm=TRUE)))
+    }
+    plot(x, y, type="l", ylim=yl, xlab="datetime", ylab="rank", xaxt="n", sub=paste("last update:", max(x), " (", outfiletype, ")", sep=""))
+    par(xaxt="s")
+    r <- as.POSIXct(round(range(x), "days"))
+    axis.POSIXct(1, at=seq(r[1],r[2], by="1 day"), format="%m/%d")
+}
+
+ylimmax <- function(ymax)
+{
+  ylm <- 10
+  while(ylm < ymax) {
+    ylm <- ylm * 10
+    while(ylm >= ymax * 2) {
+      ylm <- ylm / 2
+    }
+  }
+  return(ylm)
+}
+
+doplotrank <- function(asbn, datadir, outdir, outfiletype, topup)
+{
+  ## グラフの上下を逆にするときは出力ファイル名の拡張子前に「r」を付ける(例:475981339Xr.svg)
+  if (topup == FALSE) {
+    fname <- paste(asbn, "r", sep="")
+  } else {
+    fname <- asbn
+  }
+  ## 出力タイプ(SVGまたはPNG)の設定
+  if (outfiletype == "PNG") {
+    png(paste(outdir, "/", fname, ".png", sep=""), type="cairo", width=720, height=576)
+  } else if (outfiletype == "SVG") {
+    devSVG(paste(outdir, "/", fname, ".svg", sep=""))
+  }
+  ## グラフをファイルへ出力
+  plotrank(paste(datadir, "/", asbn, ".csv", sep=""), outfiletype, topup)
+  invisible(dev.off())
+}
+
+args <- commandArgs(trailingOnly = TRUE)
+for (ftype in c("SVG", "PNG")) {
+  for (utop in c(TRUE, FALSE)) {
+    doplotrank(args[1], args[2], args[3], ftype, utop)
+  }
+}
diff --git a/plot_batch.rb b/plot_batch.rb
new file mode 100755 (executable)
index 0000000..eb1b666
--- /dev/null
@@ -0,0 +1,43 @@
+#!/usr/local/bin/ruby
+# -*- coding: utf-8 -*-
+
+# Rプログラムのパス
+rpath = "/usr/local/bin/R"
+
+# 作業用ディレクトリのトップ
+workdir = File.expand_path("~/amazonrank")
+
+# Rのグラフ出力プログラム
+plotfile = workdir.dup << "/plot.R"
+
+# ASINリストファイル
+isbnfile = workdir.dup << "/ISBN.txt"
+
+# データCSVファイルを格納するディレクトリ
+csvdir = workdir.dup
+
+# HTMLファイルおよびデータCSVファイルを格納するディレクトリ
+htmldir = workdir.dup
+
+# プロット時のエラー記録ファイル
+ploterrfile = workdir.dup << "/error_plot.log"
+
+open(isbnfile, "r") { |lines|
+  begin
+    while isbn = lines.gets
+      isbn = isbn.chomp
+      cmd = rpath.dup << " --vanilla --slave --args " << isbn.dup << " " << csvdir.dup << " " << htmldir.dup << " <" << plotfile.dup << " 2>>" << ploterrfile.dup
+      system(cmd)
+      raise "ASIN:" << isbn.dup << " コマンド実行エラー" if $? != 0
+    end
+  rescue => exc
+    STDERR.puts exc
+    errfile = File.expand_path(ploterrfile.dup)
+    open(errfile, "a") { |f|
+      f.print "ASIN: ", isbn, "\n"
+      f.print "日時: ", Time.now.strftime("%Y/%m/%d %H:%M:%S"), "\n"
+      f.print "\n"
+    }
+    retry
+  end
+}