by shigemk2

当面は技術的なことしか書かない

RubyGems kindle-highlightsを使ってみたけどダメだった

リンク

kindle-highlights - Kindleで付けたハイライト部分をスクレイピングを使って取得|オープンソース・ソフトウェア、ITニュースを毎日紹介するエンジニア、デザイナー向けブログ

speric/kindle-highlights · GitHub

サンプル

require 'kindle_highlights'

# pass in your Amazon credentials. Loads your books (not highlights) on init, so might take a while                                                             
kindle = KindleHighlights::Client.new("sgt.pepper@lonelyhearts.com", "mr_kite") 

p kindle.books # これでKindleの本一覧が表示される筈であった

問題発生

kindle.booksにkindleで購入した本の一覧がhashで格納されている筈なのだが、あきらかに本の数が少ない。

それもそのはず、ログインしているのは kindle.amazon.com のほうであって、 kindle.amazon.co.jp じゃないからである。jpで購入したKindleはjpにデバイス登録されるけど comのほうには登録されていない。

ためしにkindle.amazon.comにログインしてハイライトを見たけど1つも表示されてなかった。

com と jp を統合する方法はあるにはあるのだが、サポートに連絡をとるのが面倒というオレオレな理由で却下。

gemを直接弄る

Bundler再履修: bundle execって何? gemはどこに入るの? - memo.yomukaku.net

とりあえず

$ type ruby

するとかして、gemがどこのディレクトリにインストールされているかを調べる。

なお、ぼくはディレクトリを作ってGemfileを作り bundle install でkindle-highlightsをインストールしている。

~/.rbenv/versions/1.9.3-p392/lib/ruby/gems/1.9.1/gems/kindle-highlights-0.0.8/lib/kindle_highlights.rb

require 'rubygems'
require 'mechanize'
require 'json'
require 'kindle_highlights/client'

module KindleHighlights  
  
  KINDLE_LOGIN_PAGE      = "http://kindle.amazon.com/login"
  SIGNIN_FORM_IDENTIFIER = "signIn"
end

はい、案の定。

KINDLE_LOGIN_PAGE の URL を http://kindle.amazon.co.jp/login に差し替える。

~/.rbenv/versions/1.9.3-p392/lib/ruby/gems/1.9.1/gems/kindle-highlights-0.0.8/lib/kindle_highlights/client.rb

module KindleHighlights
  class Client
    attr_reader :books
        
    def initialize(email_address, password)
      @email_address = email_address
      @password      = password
      @books         = Hash.new
      
      setup_mechanize_agent
      load_books_from_kindle_account
    end
  
    def highlights_for(asin)
      highlights = @mechanize_agent.get("https://kindle.amazon.com/kcw/highlights?asin=#{asin}&cursor=0&count=1000")
      json = JSON.parse(highlights.body)
      json["items"]
    end
    
    private
   
    def load_books_from_kindle_account
      signin_page = @mechanize_agent.get(KINDLE_LOGIN_PAGE)
      
      signin_form = signin_page.form(SIGNIN_FORM_IDENTIFIER)
      signin_form.email = @email_address
      signin_form.password = @password
      
      kindle_logged_in_page = @mechanize_agent.submit(signin_form)
      highlights_page = @mechanize_agent.click(kindle_logged_in_page.link_with(text: /Your Books/))

      loop do
        highlights_page.search(".//td[@class='titleAndAuthor']").each do |book|
          asin_and_title_element = book.search("a").first
          asin = asin_and_title_element.attributes["href"].value.split("/").last
          title = asin_and_title_element.inner_html
          @books[asin] = title
        end
        break if highlights_page.link_with(text: /Next/).nil?
        highlights_page = @mechanize_agent.click(highlights_page.link_with(text: /Next/))
      end
    end
    
    def setup_mechanize_agent
      @mechanize_agent = Mechanize.new
      @mechanize_agent.user_agent_alias = 'Windows Mozilla'
      @mechanize_agent.agent.http.verify_mode = OpenSSL::SSL::VERIFY_NONE
    end
  end
end

同様のところで、highlightsのURLを.co.jpに差し替える。

highlights = @mechanize_agent.get("https://kindle.amazon.co.jp/kcw/highlights?asin=#{asin}&cursor=0&count=1000")

実行、エラー、そして諦める

kindle.rb

# -*- coding: utf-8 -*-
require 'kindle_highlights'

# pass in your Amazon credentials. Loads your books (not highlights) on init, so might take a while
kindle = KindleHighlights::Client.new('id', 'passwd')
p kindle.highlights_for('B00F3UTIQY')
$ ruby kindle.rb
/Users/shige/.rbenv/versions/1.9.3-p392/lib/ruby/gems/1.9.1/gems/mechanize-2.7.3/lib/mechanize/http/agent.rb:308:in `fetch': 500 => Net::HTTPInternalServerError for https://kindle.amazon.co.jp/kcw/highlights?asin=B00F3UTIQY&cursor=0&count=1000 -- unhandled response (Mechanize::ResponseCodeError)