糞糞糞ネット弁慶

読んだ論文についてメモを書きます.趣味の話は http://repose.hatenablog.com

Ameblo/Livedoor/excite/yaplog のブログクローラ書いた

ブログ記事を収集する必要が生じてクローラ書いた.
最初は

wget -a ./wget.log -w 30 -r -np -m -k -erobots=off -np blog_url

とかやってたけど月別一覧やカテゴリ一覧,モバイル版URLを開こうとしてかなり重複してしまい一向に終わらないので,主要なブログサービスに合わせて書いた.
どこから辿るのが記事を網羅できるか考えたところ

  • Livedoor: base_url/archives/year-month.html?p=pos
    • 続きがあるかどうかの判定,ブログによってまちまちなのでキーワードマッチにした
  • Ameblo: base_url/archive#{pos}-#{year}#{month}.html
  • excite: base_url/page/#{pos}
  • yaplog: base_url/#{pos}
    • base_url/monthly/#{year}#{month}/ で辿る方法もあるけどブログによって記事が全表示されるものと記事タイトルだけが出るものがあったので面倒に見えた

でたどるのが一番良さそうだった.
year/monthに当たる部分は2003年から決め打ちで書いた.ここ二分探索とかして記事が書かれ始めた年月を特定するとかすればもっと賢くなると思う.
とりあえず全記事これで落ちてくるはずなのでダウンロード後に個別記事ごとに切り出すとかすればいいと思う.

# -*- coding: utf-8 -*-
require 'nokogiri'
require 'open-uri'
WAIT_SEC = 30
UA = ''

def get_ameblo(base_url, save_path)
  base_url.sub!(/\/$/, "")

  2003.upto 2012 do |y|
    1.upto 12 do |m|
      m = "0#{m}" if m < 10
      pos = 1
      loop do
        url = "#{base_url}/archive#{pos}-#{y}#{m}.html"
        sleep WAIT_SEC
        begin
          doc = Nokogiri::HTML(open(url, 'User-Agent' => UA).read)

          # save
          open("#{save_path}/archive#{pos}-#{y}#{m}.html", 'w'){|f|
            f.puts doc.inner_html
          }

          # 次が存在するかどうか
          end_flag = (doc/'a.nextPage').empty?
          break if end_flag
        rescue => e
        end
        pos += 1
      end
    end
  end
end

def get_excite(base_url, save_path)
  base_url.sub!(/\/$/, "")

  pos = 1

  loop do
    url = "#{base_url}/page/#{pos}"
    sleep WAIT_SEC
    begin
      doc = Nokogiri::HTML(open(url, 'User-Agent' => UA).read)

      # save
      open("#{save_path}/#{pos}.html", 'w'){|f|
        f.puts doc.inner_html
      }

      # 次があるかどうか
      end_flag = (doc/'a.older_page').empty?
      break if end_flag
    rescue => e
    end
    pos += 1
  end
end

def get_livedoor(base_url, save_path)
  base_url.sub!(/\/$/, '')

  2003.upto 2012 do |y|
    1.upto 12 do |m|
      m = "0#{m}" if m < 10
      pos = 1
      loop do
        page_url = "#{base_url}/archives/#{y}-#{m}.html?p=#{pos}"
        sleep WAIT_SEC
        begin
          doc = Nokogiri::HTML(open(page_url, 'User-Agent' => UA).read)
          # 保存
          open("#{save_path}/#{y}-#{m}.html_#{pos}", 'w'){|f|
            f.puts doc.inner_html
          }
          # テーマによって next 要素のあるなしが違うのでめんどくさいから
          # 次記事の URL があるかどうかのマッチで探す
          next_url = "#{base_url}/archives/#{y}-#{m}.html?p=#{pos + 1}\""
          end_flag = !doc.inner_html.include?(next_url)
          break if end_flag
        rescue => e
        end
        pos += 1
      end
    end
  end
end

def get_yaplog(base_url, save_path)
  base_url.sub!(/\/$/, "")

  pos = 1

  loop do
    url = "#{base_url}/#{pos}"
    sleep WAIT_SEC
    # 恐らく不完全な HTML が返ってくることがあり,
    # そのために Nokogiri での parse が失敗する
    # なので, open(url).read の中身をそのまま見る
    begin
      doc = open(url, 'User-Agent' => UA).read

      # save
      open("#{save_path}/#{pos}.html", 'w'){|f|
        f.puts doc
      }

      # check
      next_link = base_url + '/' + (pos + 1).to_s + '"'
      end_flag = !doc.include?(next_link)
      break if end_flag
    rescue => e
    end
    pos += 1
  end
end