sqlite3って、データ型が以下しかないんですって。
TEXT | テキストデータ |
NUMERIC | 数値 |
INTEGER | 整数 |
REAL | 小数点などを含むリアル値 |
NONE | 形式なし |
データを格納する時には以下が要注意ですって。
まぁ形式はなるべく守るべきよね。
ところで上を見ればわかると思うけど、時制を入れる先がないのよね。悩んだ末にこんな題材を作って見たの。
NHKのサイトを見ればわかるけど、ニュースをジャンル別にRSSでも配信しているの。もちろんこれには日付データもついてる。
これを取り込んで、新しい順番にソートしたいとしましょうか。
sql = <<SQL CREATE TABLE nhknews ( yymmdd integer, date text, genre text, desc text, link text, title text ); SQL
名前はNHKニュース、内容は以下の通りね。
yymmdd | integer | 日付を20161102のように整数にして格納。 |
date | text | 変換前の日付データ |
genre | text | ジャンル(総合ニュースとか社会ニュースとか) |
desc | text | ニュース本文 |
link | text | ニュースのURL |
title | text | ニュースタイトル |
次に格納処理を書きましょう。RSS処理部は本題じゃないので省略するわね。
再度呼び出す場合もあるので、一度読みだして更新する処理も含めてあるわ。
みればわかるけど、以下の原則の元に書いてあるわ。
あと総数が大した量じゃないので一度全部読み込んでるのよね。これはもちろん、データ数が膨れ上がる種類のデータなら要注意というか、その時は最初から日付指定で読み出しを考えなくちゃならないと思う。
#!/usr/bin/ruby -EUTF-8 require 'rss' require 'sqlite3' require 'time' class Kiji def initialize(title,link,pubDate,desc,genre) @title = title.clone @link = link.clone @pubDate = pubDate.clone @yymmdd = nil begin if @pubDate.class == String x2 = @pubDate.gsub(/(年|月)/,'/') x2.gsub!(/(日|秒)/,'') x2.gsub!(/(時|分)/,':') @pubDate = Time.parse(x2) end @yymmdd = @pubDate.to_yymmdd rescue p @pubDate.class end @desc = desc.clone @genre = genre.clone end attr_accessor :title,:link,:pubDate,:yymmdd,:desc,:genre end class Time def to_yymmdd self.strftime("%Y%m%d%H%M%S").to_i end end class Array2 < Array def getRss(url) rss = RSS::Parser.parse(url) genre = rss.channel.title.gsub(/NHKニュース\|/,'') if genre =~ /NHK/ genre = "総合" end rss.items.each{|item| n = Kiji.new(item.title, item.link, item.pubDate, item.description, genre) self.push(n) } end end Dir.chdir(File.dirname(__FILE__)) db = SQLite3::Database.new("news1.db") debug = false debug = true if ARGV.length > 0 && ARGV[0] =- "true" s = [] begin # 読み出し db.execute('select * from nhknews') do |row| s.push(row) end rescue print "データがなさげなのでテーブル生成:" sql = <<SQL CREATE TABLE nhknews ( yymmdd integer, date text, genre text, desc text, link text, title text ); SQL # テーブル生成 db.execute(sql) print "OK\n" end s2 = [] if s.length > 0 s.each{|d| if d.class == Array s2.push(Kiji.new(d[5],d[4],d[1],d[3],d[2])) end } end # データ書き込みパターン設定 sql = "insert into nhknews values (?, ?, ?, ?, ?, ?)" ss = Array2.new ss.getRss("(NHKニュースRSSのあるURL(よそのURLなので直接記載は避けます))") ss.each{|n| ff = false s2.each{|d| if d.yymmdd == n.yymmdd ff = true break end } if ff == true p "OK!#{n.title}" else db.execute(sql, n.yymmdd, n.pubDate.strftime("%Y年%m月%d日 %H時%M分%S秒"), n.genre,n.desc,n.link,n.title) print <<EOM [#{n.genre}] #{n.title} (#{n.pubDate}) #{n.yymmdd} #{n.link} #{n.desc} EOM end }
さぁ、それじゃ登録したデータを読みこんでみましょうか。
なお「ORDER BY データ名 DESC」は指定データ名による降順ソート(昇順はASC)。うん、便利ねSQL。
k = 30 tday = false begin k2 = k - 1 db = SQLite3::Database.new("news1.db") datas = db.execute("SELECT yymmdd,date,title,desc,link FROM nhknews ORDER BY yymmdd DESC") s = [] datas.each do |d| s.push(UNews.new(d[0],d[1],d[2],d[3],d[4])) end db.close s = s[0..k2] if s.length > k ff = false s.each{|d| og = "" og = "次のニュースです。" if ff == true date = d.date.clone if date =~ /#{today}/ date.gsub!(/#{today}/,"本日") end next if tday == true && date !~ /本日/ # 今日だけ設定ならそれ以外を飛ばす。 print <<EOM
<dt>#{og}#{date.gsub(/^.+年/,'')} #{d.title}。</dt> <dd>#{d.desc}</dd>
EOM ff = true } print "\n<dl>\n<p>#{caution}</p>\n#{tail}" rescue => e print "DBアクセスでエラーになった。(#{e.message})\n" exit end