SQlite3を使ってみる。 - Ruby

sqlite3って、データ型が以下しかないんですって。

TEXTテキストデータ
NUMERIC数値
INTEGER整数
REAL小数点などを含むリアル値
NONE形式なし

データを格納する時には以下が要注意ですって。

まぁ形式はなるべく守るべきよね。

ところで上を見ればわかると思うけど、時制を入れる先がないのよね。悩んだ末にこんな題材を作って見たの。

演習「NHKニュースを格納してみましょう」

NHKのサイトを見ればわかるけど、ニュースをジャンル別にRSSでも配信しているの。もちろんこれには日付データもついてる。

これを取り込んで、新しい順番にソートしたいとしましょうか。

DBテーブルの作成

sql = <<SQL
 CREATE TABLE nhknews (
 yymmdd integer,
 date text,
 genre text,
 desc text,
 link text,
 title text
);
SQL

名前はNHKニュース、内容は以下の通りね。

yymmddinteger日付を20161102のように整数にして格納。
datetext変換前の日付データ
genretextジャンル(総合ニュースとか社会ニュースとか)
desctextニュース本文
linktextニュースのURL
titletextニュースタイトル

次に格納処理を書きましょう。RSS処理部は本題じゃないので省略するわね。

DBテーブルへの登録処理

再度呼び出す場合もあるので、一度読みだして更新する処理も含めてあるわ。

みればわかるけど、以下の原則の元に書いてあるわ。

あと総数が大した量じゃないので一度全部読み込んでるのよね。これはもちろん、データ数が膨れ上がる種類のデータなら要注意というか、その時は最初から日付指定で読み出しを考えなくちゃならないと思う。

#!/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
}

DBデータの読み出し

さぁ、それじゃ登録したデータを読みこんでみましょうか。

なお「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

トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-11-02 (水) 10:42:17