はてなブックマークから指定されたタグのエントリを削除する。

こちらを参考に作成。

require 'net/http'
require 'digest/sha1'
require 'rexml/document'
require 'time'

$kcode = 'u'

Net::HTTP.version_1_2

def x_wsse(username, password)
    nonce   = Array.new(10){ rand(0x100000000) }.pack('I*')
    created = Time.new.utc.iso8601
    digest  = Digest::SHA1.digest(nonce + created + password)
    wsse    = "UsernameToken Username=#{username}, ",
              "PasswordDigest=#{[digest].pack('m').chomp}, ",
              "Nonce=#{[nonce].pack('m').chomp}, ",
              "Created=#{created}"
    { 'x-wsse' => wsse.to_s }
end

user = 'username'            # はてなのユーザ名
pass = 'password'            # はてなのパスワード
tag = 'tag'                  # 処理対象のタグ
entries = {}

Net::HTTP.start('b.hatena.ne.jp') do |http|
  
  has_next = true
  start = 0

  # 認証ヘッダ取得
  header = x_wsse(user, pass)

  while has_next
    response = http.get(
                        "/atom/feed?tag=#{tag}&of=#{start}",
                        header
                        )

    doc = REXML::Document.new(response.body)

    open('doc.xml', 'w') { |f| f.puts(doc.to_s)}
    
    # 一度に取得できる件数を取得(tagで検索するとページングする)
    per_page_elem = doc.elements['/feed/openSearch:itemsPerPage']
    if per_page_elem
      items_par_page = per_page_elem.text.to_i
    end

    # エントリのIDとURLを取得
    doc.each_element('/feed/entry') do |entry|
      id = entry.elements['id'].text.scan(/\A.*-([0-9]+)\Z/).to_s
      url = entry.elements['link[@rel="related"]'].attributes['href']
      entries[id] = url
    end

    # 次ページがあるかどうかを判定
    has_next = doc.elements['feed/link[@rel="next"]'] ? true : false
    if has_next
      start += items_par_page
    end

  end

  # 削除するエントリをバックアップ
  File.open('backup.txt', 'w') do |file|
    entries.each_value do |url|
      file.puts(url)
      puts url
    end
  end

  # エントリを削除
  entries.each_key do |id|
    http.delete("/atom/edit/#{id}", header)
  end

end

もし使用される方がいた場合の注意点

  • 一応、削除したエントリのURLをバックアップしていますが、復元は手動になるのでお気をつけください
    • 私はテスト中に間違って消してしまい、涙しました
  • tagを空白にすると全件が削除対象となります
  • 処理には結構、時間がかかりますので終了するまで気長にお待ちください
  • スクリプトでエントリを削除した後、ブラウザ上で確認すると削除されていますが、再度、APIからアクセスすると削除されたエントリが取得されます
    • 何故かはよくわからないです
    • 反映されるまでに時間がかかるのでしょうか。