読者です 読者をやめる 読者になる 読者になる

undefined

bokuweb.me

無料の電子書籍を検索できるWEBサービス作った


kindleなんかはゲリラ的に無料セールを行う上に情報が取りにくいので特化したものを作った。 厳密には作ったまま放置していたのを最近動かしはじめた。

なにこれ?

f:id:bokuweb:20151212235631p:plain

Kindle, kobo, yahoo!ブックスから無料電子書籍を検索できます。

shelf.bokuweb.me

技術的な話

構成

その名を聴かなくなって久しい(?)MEANで学習用に夏くらいに作りました。 Openshiftで動かしてます。

主なパッケージ

サーバーサイド

名称 概要
apac Amazon Product AdvertisingのNode.jsクライアント
cheerio-httpcli HTMLパース付きNode.js用HTTPクライアントモジュール
config 設定用
cron 書籍データのフェッチを定期実行
ect テンプレート
mongoose MongoDB用object modeling tool
request 楽天APIリクエスト用

クライアントサイド

coffeeで書いてた。

名称 概要
angular 1.4.3使ってた
angular-resource resource
ngInfiniteScroll 無限スクロール

やってること

node-cronで定期的に書籍データをとりmongoDBにつっこむ

node-cronで制限に引っかからない程度の周期で、書籍データの取得を行いmongoDBを更新していっている。無料電子書籍は期間限定のものなど無料から通常価格へ移行するものがあるので、走査後に更新がなかったものは削除している。

Kindleからの取得

kindleはapacMaximumPriceを0にして取ってきている。昔は一つの検索条件で4000商品取得できたようだけど、現在は10件×10ページの100商品しか取得できないため、検索条件を変えながら走査している。

Kindleはカテゴリ毎にブラウザノードと呼ばれる番号があるのでそいつを指定しながら走査していった。具体的には以下。categoryはこっちで勝手に定義したもの。

browserNodes = [
  {node : '漫画雑誌'                       , category : '雑誌'                   , id : 3386054051} # 14
  {node : '小説・文芸'                     , category : '文学・評論'             , id : 2292754051}
  {node : '歴史・時代小説'                 , category : '文学・評論'             , id : 2292767051}
  {node : '経済・社会小説'                 , category : '文学・評論'             , id : 2292768051}
  {node : 'ミステリー・サスペンス'         , category : '文学・評論'             , id : 2292724051}
  {node : 'SF・ホラー・ファンタジー'       , category : '文学・評論'             , id : 2292700051}
  {node : 'ロマンス'                       , category : '文学・評論'             , id : 2292725051}
  {node : 'エッセー・随筆'                 , category : '文学・評論'             , id : 2292701051}
  {node : '古典'                           , category : '文学・評論'             , id : 2292736051}
  {node : '詩歌'                           , category : '文学・評論'             , id : 2292788051}
  {node : '戯曲・シナリオ'                 , category : '文学・評論'             , id : 2292753051}
  {node : '伝承・神話'                     , category : '文学・評論'             , id : 2292726051}
  {node : '全集・選書'                     , category : '文学・評論'             , id : 2292727051}
  {node : '評論・文学研究'                 , category : '文学・評論'             , id : 2292769051}
  {node : '哲学・思想'                     , category : '人民・思想'             , id : 2292103051}
  {node : '倫理学・道徳'                   , category : '人民・思想'             , id : 2292096051}
  {node : '宗教'                           , category : '人民・思想'             , id : 2292172051}
  {node : '心理学'                         , category : '人民・思想'             , id : 2292260051}
  {node : '文化人類学・民俗学'             , category : '人民・思想'             , id : 2292272051}
  {node : '言語学'                         , category : '人民・思想'             , id : 2292324051}
  {node : '女性学'                         , category : '人民・思想'             , id : 2292166051}
  {node : '教育学'                         , category : '人民・思想'             , id : 2292640051}
  {node : '本・図書館'                     , category : '人民・思想'             , id : 2292281051}
  {node : '政治'                           , category : '社会・政治'             , id : 2293175051}
  {node : '外交・国際関係'                 , category : '社会・政治'             , id : 2293164051}
  {node : '軍事'                           , category : '社会・政治'             , id : 2293255051}
  {node : '法律'                           , category : '社会・政治'             , id : 2293195051}
  {node : '社会学'                         , category : '社会・政治'             , id : 2293229051}
  {node : '福祉'                           , category : '社会・政治'             , id : 2293247051}
  {node : 'コミュニティ'                   , category : '社会・政治'             , id : 2293151051}
  {node : '環境・エコロジー'               , category : '社会・政治'             , id : 2293228051}
  {node : 'NGO・NPO'                       , category : '社会・政治'             , id : 2293150051}
  {node : 'マスメディア'                   , category : '社会・政治'             , id : 2293154051}
  {node : '参考図書'                       , category : '社会・政治'             , id : 2293163051}
  {node : 'ノンフィクション'               , category : 'ノンフィクション'       , id : 2291791051} # 9
  {node : '歴史学'                         , category : '歴史・地理'             , id : 2293141051}
  {node : '日本史'                         , category : '歴史・地理'             , id : 2293114051}
  {node : '世界史'                         , category : '歴史・地理'             , id : 2293077051}
  {node : '考古学'                         , category : '歴史・地理'             , id : 2293142051}
  {node : '地理・地域研究'                 , category : '歴史・地理'             , id : 2293103051}
  {node : '地図'                           , category : '歴史・地理'             , id : 2293098051}
  {node : '参考図書'                       , category : '歴史・地理'             , id : 2293097051}
  {node : 'ビジネス・経済'                 , category : 'ビジネス・経済'         , id : 2291905051} # 81
  {node : '投資・金融・会社経営'           , category : '投資・金融・会社経営'   , id : 2292576051} # 13
  {node : '科学読み物'                     , category : '科学・テクノロジー'     , id : 2293350051}
  {node : '数学'                           , category : '科学・テクノロジー'     , id : 2293312051}
  {node : '物理学'                         , category : '科学・テクノロジー'     , id : 2293321051}
  {node : '化学'                           , category : '科学・テクノロジー'     , id : 2293268051}
  {node : '宇宙学・天文学'                 , category : '科学・テクノロジー'     , id : 2293286051}
  {node : '地球科学・エコロジー'           , category : '科学・テクノロジー'     , id : 2293279051}
  {node : '金属・鉱学'                     , category : '科学・テクノロジー'     , id : 2293358051}
  {node : '生物・バイオテクノロジー'       , category : '科学・テクノロジー'     , id : 2293291051}
  {node : '工学'                           , category : '科学・テクノロジー'     , id : 2293291051}
  {node : 'エネルギー'                     , category : '科学・テクノロジー'     , id : 2293264051}
  {node : '電気・通信'                     , category : '科学・テクノロジー'     , id : 2293359051}
  {node : '農学'                           , category : '科学・テクノロジー'     , id : 2293351051}
  {node : '海洋学'                         , category : '科学・テクノロジー'     , id : 2293318051}
  {node : '参考図書'                       , category : '科学・テクノロジー'     , id : 2293275051}
  {node : 'コンピュータ・IT'               , category : 'コンピュータ・IT'       , id : 2291657051} # 22
  {node : '写真'                           , category : '趣味・スポーツ・美術'   , id : 2291492051}
  {node : '絵画'                           , category : '趣味・スポーツ・美術'   , id : 2291531051}
  {node : '彫刻・工芸'                     , category : '趣味・スポーツ・美術'   , id : 2291520051}
  {node : '芸術一般'                       , category : '趣味・スポーツ・美術'   , id : 2291538051}
  {node : 'コンテンポラリーアート'         , category : '趣味・スポーツ・美術'   , id : 2291483051}
  {node : '作品集'                         , category : '趣味・スポーツ・美術'   , id : 2291491051}
  {node : '建築'                           , category : '趣味・スポーツ・美術'   , id : 2291497051}
  {node : '住宅建築・家づくり'             , category : '趣味・スポーツ・美術'   , id : 2291490051}
  {node : 'インテリアデザイン'             , category : '趣味・スポーツ・美術'   , id : 2291482051}
  {node : 'デザイン'                       , category : '趣味・スポーツ・美術'   , id : 2291486051}
  {node : '日本の伝統文化'                 , category : '趣味・スポーツ・美術'   , id : 2291526051}
  {node : '古美術・骨董'                   , category : '趣味・スポーツ・美術'   , id : 2291496051}
  {node : '美術館・博物館'                 , category : '趣味・スポーツ・美術'   , id : 2291537051}
  {node : 'モード'                         , category : '趣味・スポーツ・美術'   , id : 2291489051}
  {node : '参考図書'                       , category : '趣味・スポーツ・美術'   , id : 2291495051}
  {node : '趣味・実用'                     , category : '趣味・スポーツ・美術'   , id : 2292479051} # 133
  {node : 'スポーツ・アウトドア'           , category : '趣味・スポーツ・美術'   , id : 2292480051} # 81
  {node : '資格・検定・就職'               , category : '語学・学習・教育・資格' , id : 2293536051} # 2
  {node : '暮らし・健康・子育て'           , category : '暮らし・健康・子育て'   , id : 2292803051} # 110
  {node : '語学・辞事典・年鑑'             , category : '語学・学習・教育・資格' , id : 2292799051} # 88
  {node : '教育・受験'                     , category : '語学・学習・教育・資格' , id : 2292600051} # 55
  {node : '絵本'                           , category : '絵本・児童書'           , id : 2293383051}
  {node : '読み物'                         , category : '絵本・児童書'           , id : 2293384051}
  {node : 'ノンフィクション・伝記'         , category : '絵本・児童書'           , id : 2293368051}
  {node : '学習'                           , category : '絵本・児童書'           , id : 2293370051}
  {node : 'お絵かき・うた・音楽'           , category : '絵本・児童書'           , id : 2293364051}
  {node : '実用・工作・趣味'               , category : '絵本・児童書'           , id : 2293381051}
  {node : 'クイズ・パズル・ゲーム'         , category : '絵本・児童書'           , id : 2293365051}
  {node : 'スポーツ'                       , category : '絵本・児童書'           , id : 2293367051}
  {node : '図鑑・事典・年鑑'               , category : '絵本・児童書'           , id : 2293369051}
  {node : '超能力・不思議・占い'           , category : '絵本・児童書'           , id : 2293395051}
  {node : '学習まんが'                     , category : '絵本・児童書'           , id : 2293380051}
  {node : '少年コミック'                   , category : '少年コミック'           , id : 2430812051} # 72
  {node : '青年コミック'                   , category : '青年コミック'           , id : 2430869051} # 75
  {node : '少女コミック'                   , category : '少女コミック'           , id : 2430765051} # 13
  {node : '女性コミック'                   , category : 'レディースコミック'     , id : 2430737051} # 5
  {node : 'ラノベ'                         , category : 'ラノベ'                 , id : 2410280051} # 61 
  {node : 'ボーイズラブノベルズ'           , category : 'ボーイズラブ'           , id : 2293148051} # 17
  {node : 'ボーイズラブコミックス'         , category : 'ボーイズラブ'           , id : 2293147051} # 50
  {node : '写真集'                         , category : '写真集'                 , id : 2291790051} # 1
  {node : '映画'                           , category : 'エンターテイメント'     , id : 2291605051}
  {node : '音楽'                           , category : 'エンターテイメント'     , id : 2291622051}
  {node : 'ステージ・ダンス'               , category : 'エンターテイメント'     , id : 2291589051}
  {node : 'テレビ'                         , category : 'エンターテイメント'     , id : 2291594051}
  {node : 'タレント本'                     , category : 'エンターテイメント'     , id : 2291593051}
  {node : '落語・寄席・演芸'               , category : 'エンターテイメント'     , id : 2291621051}
  {node : '演劇・舞台'                     , category : 'エンターテイメント'     , id : 2291617051}
  {node : 'サブカルチャー'                 , category : 'エンターテイメント'     , id : 2291583051}
  {node : '漫画雑誌'                       , category : '雑誌'                   , id : 3386054051} # 14                          
  {node : '雑誌'                           , category : '雑誌'                   , id : 2825265051} # 54  

これでも、小説などはパブリックドメインのものが大量にあり、走査しきれていない。全書籍を取得したかったらブラウザノード + 著者名などで検索するなどの工夫がいりそうだけど、面倒でやってない。

あとリクエストの制限は2000request/hourなんだけど、1request/5secくらいでもちょくちょく弾かれるので注意。

Koboからの取得

シンプルにURL組み立ててrequestで取ってきてる。Amazonより高速で件数もとれるのでいいんだけど、キャッシュのせいか突如商品の順序が入れ替わる問題がある。例えば、あるカテゴリの商品を1〜10ページを走査しているときに5ページ目走査後順序が入れ替わり、6ページ目移行に1〜5ページで走査完了済の商品が登場したりする。走査回数を増やしたりして、網羅性を高めているんだけど、取りこぼしは発生していて根本対策にはなっていない。

Yahoo!ブックストアからの取得

cheerio-httpcliでのんびり取ってきている。cheerio-httpcliは記事にしたこともあるけど、かなり便利。例えば以下でyahoo!のニュース一覧をとってこれる。 ※ coffeeです。

client = require('cheerio-httpcli')
client.fetch 'http://www.yahoo.co.jp/', {}, (err, $, res)->
  $('ul.emphasis > li > a').each ()-> console.log $(this).text()

作ってみて

  • あくまで自分にとってはだけど、ノイズが多く感じた。各カテゴリでfeed吐くようにして興味のあるカテゴリだけ購読すると便利かも。
  • 重複を放置しているとはいえ15000点以上の無料書籍が登録されており、まじか、ってなった。
  • 他にも電子書籍サービスはいくつもあるんだけど、ほとんどKindleで網羅されており、Kindleすごいってのと他のサービス大丈夫か?って感想が同時によぎった。やはりkindle最強では。
  • 洋書も対応したほうがよいかも。