2ちゃんねるBOTの作り方 実装編2

2ちゃんねるBOTの作り方 準備編 - GIOの日記
2ちゃんねるBOTの作り方 設計編 - GIOの日記
2ちゃんねるBOTの作り方 実装編1 - GIOの日記

同じファイルをダウンロードしないようにしよう

この機能は実装方法に悩む
1.DATを前回読み込んだ分だけシークさせて、残りから画像を探す
2.ダウンロードした画像URLをDBにいれとく
3.前回ダウンロードした枚数回はダウンロードしない
2は無いとして、1がベストだと思うが、一番最初に思いついた3を実装します。
Appクラスを変更。yaml/storeでDAT番号をキーに枚数を永続化

class App
  def execute(board)
    root_dir = File.dirname(__FILE__)
    image_dir = "#{root_dir}/images"
    # 
    db = YAML::Store.new("#{root_dir}/log/thread.db")
    menu = Menu.new
    board = menu.get_board(board)
    threads = board.get_threads
    puts "total: #{threads.length} threads"
    threads.each do |thread|
      images = thread.get_images rescue next
      next if images.empty?
      parent_dir = "#{image_dir}/#{thread.dat_no}" 
      Dir.mkdir(parent_dir) unless File.exists?(parent_dir)
      puts "#{thread.title}: #{images.length} pics"
      #
      downloaded = db.transaction { db[thread.dat_no] } || 0
      images.each_with_index do |image, index|
        #
        next if index < downloaded
        image.download("#{parent_dir}/#{index}.jpg") rescue next
      end
      #
      db.transaction { db[thread.dat_no] = images.length }
    end
  end
end

イメぴたに対応してみよう

イメぴたは普通のアップローダーと違い画像の直リンクではないので、別に対応が必要です。イメぴたのURLはこんなの

http://imepita.jp/20090219/832920

そして

http://imepita.jp/image/20090219/832920

に接続すると画像ファイルにリダイレクトされるようになってます。ただし、適切にRefererを設定しないとリダイレクトされません。

ということで実装します。ついでに共通化。DRY!

class Downloader
  attr_accessor :uri, :url

  def initialize(url)
    @url = url
    @uri = URI.parse(@url)
  end

  def save(res, saveTo)
    puts "download: #{url}"
    case res
    when Net::HTTPSuccess
      open(saveTo, 'wb') do |f|
        f.write res.body
      end
    end
  end
end

class NormalImageDownloader < Downloader
  def download(saveTo)
    http = Net::HTTP.new(uri.host, 80)
    res = http.get(uri.path)
    save(res, saveTo)
  end

  def self.match(url)
    url =~ /.jpg$/i
  end
end

class ImepitaDownloader < Downloader
  def download(saveTo)
    http = Net::HTTP.new(uri.host, 80)
    headers = {'Referer' => url}
    res = http.get("/image#{uri.path}", headers)
    save(res, saveTo)
  end

  def self.match(url)
    url =~ /\/\/imepita.jp\/\d+\/\d+/i
  end
end

動かす

ruby bot2ch.rb

ちなみに完走させてみたら、1500枚くらいダウンロードされた。ひどすぎる。
あとは手動で実行するなり、デーモン化してループさせるなり、cronやタスクスケジューラ?で定期的に動かすなりお好きなように。


コードはコチラ


本気で動かすなら

今回は分かりやすくする為にシンプルに実装しましたが、本気で使うならば

  • しっかり例外処理をする
  • 言語変えたり、Thread使ったりして高速化
  • ダウンロードしたファイルをチェック(ダミー多数)
  • 複数同時にダウンロードする場合、相手に迷惑をかけない。

等の対応が必要です。

最後に

ということでコレクターはオリジナル画像をダウンロードしたら良いと思いますよ。
見るだけなら2ch画像まとめがオススメ
2chは画像以外にもアホなものが多数あるので、面白いものがまだまだ作れそうです。


2ちゃんねるBOTの作り方 完