Ruby - PrawnでTweetリストPDF作成!
Updated:
少し前に「Ruby - PrawnでPDF作成!」で公開したとおり、Rubyで「Pwarn」Gemパッケージを使用してPDFを作成する方法を紹介しました。
今回はPDF作成処理を実用化してみました。
独学で習得したものなので、あまり綺麗ではありませんがソース(Linux版)を公開します。 参考になれば幸いです。
前提条件
- Linux(当方はScientificLinux6.0)を使用している。
- LinuxにRuby(当方はRuby1.9.2-p290)がインストールされている。
- LinuxにMySQLがインストールされていて、使用するテーブルが作成されている。
- Ruby Gemパッケージ「mysql2」がインストールされている。
- Ruby Gemパッケージ「sanitize」がインストールされている。 (過去記事「Ruby - Sanitize Gemパッケージのインストール!」も参照)
- Ruby Gemパッケージ「prawn」がインストールされている。
Rubyスクリプト
MySQLに保存している自分のTwitterのツイートを一覧にするPDF作成スクリプトです。 Windows版でもほぼ同じですが、MySQLのGemパッケージは異なりますしコーディングも若干異なります。
- 「IPA P明朝」というフォントが必要です。
- Rubyスクリプト、フォントファイルの配置場所は”/home/src”ディレクトリ配下です。
- 引数を指定せずに実行すると、前月1日から前月末日の1ヶ月分を取得します。
- 引数を2つ( YYYYMMDD, YYYYMMMDD )指定すると第1引数から第2引数までの期間のデータを取得します。
- 出来上がるPDFのファイル名は”TweetList_YYYYMMDD-YYYYMMDD.pdf”で保存先は”/home/src/twitter”です。
ファイル名:twitter_make_pdf_tweet.rb
# -*- coding: utf-8 -*-
#-------------------------------------
# 引数 : 無し
# or
# 第1:99999999(取得開始年月日(YYYYMMDD))
# 第2:99999999(取得終了年月日(YYYYMMDD))
#-------------------------------------
require 'mysql2'
require 'date'
require 'sanitize'
require 'kconv'
require 'prawn'
class TwitterMakePdfTweet
# DB(MySQL)接続情報
$DB = 'hoge'
$HOST = '127.0.0.1'
$USER = 'hoge'
$PASSWORD = 'hogehoge'
# [CLASS] 引数
class Arg
# INITIALIZE
def initialize()
# 引数取得
@date_f = ARGV[0].to_s
@date_t = ARGV[1].to_s
end
# 引数チェック
def get_date()
begin
# 引数が無い場合
# 取得開始年月日:前月1日
# 取得終了年月日:前月末日
if @date_f == "" && @date_t == ""
# 今日日付取得
date_today = Date.today
# 今月1日取得
date_this_month_first = Date.new(date_today.year, date_today.month, 1)
# 前月1日取得
date_last_month_first = date_this_month_first << 1
date_f = date_last_month_first.strftime( "%Y%m%d" )
# 前月末日取得
date_last_month_last = date_this_month_first - 1
date_t = date_last_month_last.strftime( "%Y%m%d" )
# 引数がある場合
# 第1引数[取得開始年月日]の妥当性チェック
# 第2引数[取得終了年月日]の存在チェック
# 第2引数[取得終了年月日]の妥当性チェック
# (第3引数以降は無視)
else
# 第1引数[取得開始年月日]が8桁の数字かチェック
if !( @date_f.to_s =~ /^\d{8}$/ )
# エラーメッセージ
str_msg = "引数[0]エラー[#{@date_f.to_s}] : 8桁の数字を指定して下さい。"
STDERR.puts( str_msg )
exit 1
end
# 第1引数[取得開始年月日]が妥当な日付かチェック
y = @date_f[0,4].to_i
m = @date_f[4,2].to_i
d = @date_f[6,2].to_i
if !Date.valid_date?( y, m, d ) # 妥当な日付ならtrue、それ以外はnilが返ってくる
# エラーメッセージ
str_msg = "引数[0]エラー[#{@date_f.to_s}] : 8桁で妥当な日付を指定して下さい。"
STDERR.puts( str_msg )
exit 1
end
date_f = @date_f
# 第2引数[取得終了年月日]の存在チェック
# 第2引数[取得終了年月日]が8桁の数字かチェック
if @date_t == "" || !( @date_t.to_s =~ /^\d{8}$/ )
# エラーメッセージ
str_msg = "引数[0] : [#{@date_f.to_s}] OK!\n"
str_msg << "引数[1]エラー[#{@date_t.to_s}] : 8桁の数字を指定して下さい。"
STDERR.puts( str_msg )
exit 1
end
# 第2引数[取得終了年月日]が妥当な日付かチェック
y = @date_t[0,4].to_i
m = @date_t[4,2].to_i
d = @date_t[6,2].to_i
if !Date.valid_date?( y, m, d ) # 妥当な日付ならtrue、それ以外はnilが返ってくる
# エラーメッセージ
str_msg = "引数[0] : [#{@date_f.to_s}] OK!\n"
str_msg << "引数[1]エラー[#{@date_t.to_s}] : 8桁で妥当な日付を指定して下さい。"
STDERR.puts( str_msg )
exit 1
end
date_t = @date_t
end
# 大小チェック
# 第1引数[取得開始年月日] > 第2引数[取得終了年月日] はエラー
if @date_f.to_i > @date_t.to_i
# エラーメッセージ
str_msg = "引数[0] : [#{@date_f.to_s}], 引数[1] : [#{@date_t.to_s}]\n"
str_msg << "引数[0] ≦ 引数[1] としてください。"
STDERR.puts( str_msg )
exit 1
end
return { :date_f => date_f,
:date_t => date_t }
rescue => e
# エラーメッセージ
str_msg = "[例外発生][" + self.class.name + ".get_date()] " + e.to_s
STDERR.puts( str_msg )
exit 1
end
end
end
# [CLASS] twitter_timelineテーブル
class TwitterTimeline
# INITIALIZE
def initialize( hash = {} )
@date_f = hash[:date_f]
@date_t = hash[:date_t]
end
# データ取得
def read_data()
begin
# データ取得開始・終了年月日
date_f = "#{@date_f[0,4]}-#{@date_f[4,2]}-#{@date_f[6,2]} 00:00:00"
date_t = "#{@date_t[0,4]}-#{@date_t[4,2]}-#{@date_t[6,2]} 23:59:59"
# MySQL 接続
my = Mysql2::Client.new( :host => $HOST,
:username => $USER,
:password => $PASSWORD,
:database => $DB )
# SQL クエリ実行 ( SELECT )
sql = "SELECT tweet_id, "
sql << " text, "
sql << " created_at, "
sql << " source "
sql << " FROM twitter_timelines "
sql << " WHERE created_at between '" + date_f + "' AND '" + date_t + "' "
res = my.query( sql, :as => :array )
return res
rescue => e
# エラーメッセージ
str_msg = "[例外発生][" + self.class.name + ".read_date()] " + e.to_s
STDERR.puts( str_msg )
exit 1
end
end
end
#################
#### メイン処理 ####
#################
begin
puts( "STARTED!!" )
# 引数取得・チェック
obj_arg = Arg.new()
res = obj_arg.get_date()
# 計算対象年月日[From, To]
date_f = res[:date_f]
date_t = res[:date_t]
puts( "[DATE_FROM] #{date_f}" )
puts( "[DATE_TO ] #{date_t}" )
# twitter_timelineテーブル
hash = { :date_f => date_f,
:date_t => date_t }
tbl_twitter_timeline = TwitterTimeline.new( hash )
# タイムラインデータ取得
res = tbl_twitter_timeline.read_data()
# 取得データ0件の場合は終了
if res.count == 0
puts( "Data Count = 0" )
puts( "FINISHED!")
exit
end
#### [START] PDF作成処理 ####
# フォントファイル設定(IPA P明朝)
FONT_FILE = 'ipamp.ttf' # Windows
# FONT_FILE = '/home/src/ipamp.ttf' # Linux
# 作成するPDFファイル名
PDF_FILE = 'TweetList_' + date_f + "-" + date_t + '.pdf' # Windows
# PDF_FILE = '/home/src/twitter/TweetList_' + date_f + "-" + date_t + '.pdf' # Linux
# pdfオブジェクトを生成
pdf = Prawn::Document.new(
:page_size => "A4", # 用紙サイズ
:page_layout => :portrait, # 用紙向き ( 縦:portrait、横:landscape )
:top_margin => 60, # 余白(上)
:left_margin => 40, # 余白(左)
:right_margin => 30 # 余白(右)
)
# フォント指定
pdf.font FONT_FILE
# 取得データ分ループ
res.each do |row|
tweet_time = Time.parse( row[2].to_s ).strftime( "%Y/%m/%d %H:%M:%S" ) # Linux対応
pdf.text "#{ tweet_time} ID[ #{row[0].to_s} ] Source[ #{Sanitize.clean(row[3].to_s)} ]"
pdf.pad(5) { pdf.text "#{Kconv.tosjis( row[1].to_s )}" }
# 下へ5px移動
pdf.move_down 5
# 罫線
pdf.stroke_horizontal_rule
# 下へ5px移動
pdf.move_down 5
end
# ページヘッダ
pdf.page_count.times do |i|
pdf.go_to_page( i + 1 )
# ページタイトル
pdf.bounding_box( [ 0, 780 ], :width => 215, :height => 15 ) do
pdf.text "Tweet一覧 [ #{ date_f.to_s } - #{ date_t.to_s } ]",
:align => :left
pdf.stroke do
pdf.line pdf.bounds.bottom_left, pdf.bounds.bottom_right
end
end
# ページ番号
pdf.number_pages "<page> / <total>",
:at => [pdf.bounds.right - 50, 780],
:width => 50,
:align => :right,
:page_filter => :all
end
pdf.render_file( PDF_FILE )
#### [E N D] PDF作成処理 ####
puts( "FINISHED!")
rescue => e
# エラーメッセージ
str_msg = "[例外発生]" + e.to_s
STDERR.puts( str_msg )
exit 1
end
end
出来栄えサンプルはTweetList_20110701-20110731。 PDF作成について、もっと細かな設定も可能ですが、今のところこれで十分だと思っています。
普段はこのRubyスクリプトをLinuxサーバ上でcron登録し、毎月1日午前0:10に引数無しで起動するようにしています。 これにより毎月自動で前月分のTweet一覧PDFが作成されます。 cron設定(/etc/cron.d/twitter)
10 0 1 * * root /usr/local/bin/ruby /home/src/twitter_make_pdf_tweet.rb > /dev/null </code></pre>
個別に出力する必要が生じた場合には、引数を指定して実行させれば対応可能です。
以上。
Comments