• スレ一覧:板のURL/subject.txt
    • ex. プログラマ板:http://kanae.2ch.net/prog/subject.txt
    • テキストはSJIS
  • レス一覧:板のURL/dat/datファイル名
    • レスは1行ごとに<>で区切られていて、名前、メール、日付、内容となっている
    • レスの取得には、httpのIf-Modified-SinceIf-None-Matchを指定してRangebytes=123-などとすると、更新があったときに差分だけ取得できる(はず)
require 'kconv'
require 'open-uri'

class TwoChannel
  # 板のスレ一覧取得
  def get_threads(ita_url)
    text = read_board_threads(ita_url)
    threads = []
    text.each_line do |line|
      line = line.toutf8.chomp
      if line =~ /(\d+\.dat)<>(.*) \((\d+)\)/
        threads << {dat_name: $1, title: $2, res_count: $3}
      end
    end
    return threads
  end

  # スレのレス一覧取得
  def get_reses(ita_url, dat_name, header = {})
    text = read_thread_reses(ita_url, dat_name, header)
    reses = []
    text.each_line do |line|
      line = line.toutf8.chomp
      name, email, date, res_html = line.split('<>')
      reses << {name: name, email: email, date: date.rstrip, res_html: res_html.strip}
    end
    return reses
  end

  private
  def read_board_threads(ita_url)
    url = "#{ita_url}subject.txt"
    return open(url).read
  end

  def read_thread_reses(ita_url, dat_name, header = {})
    url = "#{ita_url}dat/#{dat_name}"
    return open(url, header).read
  end
end

使用例:

  ita_url = 'http://kanae.2ch.net/prog/'
  two_channel = TwoChannel.new
  # スレ一覧を取得して表示
  threads = two_channel.get_threads(ita_url)
  threads.each do |thread|
    puts "#{thread[:title]}(#{thread[:res_count]})"
  end

  # 適当にスレをピックアップして、レスを表示してみる
  thread = threads[threads.size / 2]
  #thread = {:dat_name=>"1383350342.dat", :title=>"プログラマなら艦コレやってるよな?", :res_count=>"49"}

  #etag = "W/\"163e1ab-221b-4ffb481293440\""
  #last_modified = 'Sun, 03 Aug 2014 07:23:53 GMT'
  #last_bytes = 0

  header = {
    #'If-None-Match' => etag,
    #'If-Modified-Sicne' => last_modified,
    #'Range' => "bytes=#{last_bytes}-",
  }
  reses = two_channel.get_reses(ita_url, thread[:dat_name], header)
  reses.each do |res|
    puts "#{res[:name]}(#{res[:email]})[#{res[:date]}] #{res[:res_html]})"
  end