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使ったりして高速化
- ダウンロードしたファイルをチェック(ダミー多数)
- 複数同時にダウンロードする場合、相手に迷惑をかけない。
等の対応が必要です。