こんにちは!!
フィヨルドブートキャンプでWebエンジニアを目指してプログラミング習得に励んでいる@ふーがです。
この度、「cheapest-books」というパッケージをnpmに公開しました。
書籍のISBNをもとに、販売サイト上の価格情報を取得してターミナルに表示するものです。
npmへの公開手順については、別の記事でまとめました。
なぜこのようなパッケージを作ったのかや難しかった点、今後の課題なども含めて記録を残しておきます。
どういう時に使うのか
欲しい書籍がある場合に、「どこのサイトが1番安く買えるか」を確認するのに使えます。
なぜ作ったのか
僕は書籍を買う前に必ず、どこのサイトが1番安いかを確認します。 書籍の販売サイトはいくつもあるので、いちいちそれぞれのサイトにアクセスして検索して…というのが非常にめんどくさかったです。
この手間を、「少しでも減らせればいいなぁ」と思って作りました。
使い方
READMEに書いてある通りですが、ここでは日本語で書きます。
✅ インストール
ターミナルで以下のコマンドを実行してインストールします。
$ npm i -g cheapest-books
✅ 実行する
インストールが完了したら、ターミナルで起動コマンドを実行します。
$ cheapest-books
「Please enter a ISBN」と表示されて入力待ち状態になるので、価格情報を知りたい書籍のISBNを入力してEnterを押します。
※現状、13桁のISBNのみ対応しています。
? Please enter a ISBN ›
書籍のタイトルが表示されて、しばらく待つとコマンド実行時現在の、各販売サイトにおける価格情報とURLが表示されます。

実装で難しかったところ
✅ 価格情報の取得方法
当初、販売サイトのAPIを叩いて情報を取得しようと考えていたのですが、サイトによってはAPIが用意されていなかったり、あったとしてもアフィリエイトの審査が必要ですぐには使えなかったりと、制約が多いことがわかりました。
また、今後対応サイトを増やしたいという想いもあったので、「APIが用意されていないと対応できない」という状況は避けたかったです。
ですので、APIの有無にかかわらず情報を取得できる、「WEBスクレイピング」で情報を取得することにしました。
WEBスクレイピングであれば、
というメリットを感じたので、使ってみることにしました。
少し話がそれましたが、「複数ある技術要素のうち、どの方法を選ぶのか?」「本当にその方法で実現可能なのか?」「それを選ぶことでどのような影響があるのか?」といったところの考察は、経験がなかったので苦戦したポイントです。
✅ スクレイピング対象の調査
WEBスクレイピングをするライブラリとして、puppeteerを使いました。
ヘッドレスブラウザを使って対象のサイトにアクセスして情報をとってくるのですが、
実際にスクレイピングをするにあたり、
- どの要素を取得すればいいのか
- 一意になっていない要素からどうやって価格情報を取得するか
- 取扱いの有無はどうやって判定するか
などなど、問題山積みでした。
さらには、当然サイトごとに作りも違うわけですから、そこも頭を悩ませるポイントでした。
スクレイピングに優しい作りになっていないのはまぁ当然っちゃ当然なのでしょうけど…。
この点は愚直に各サイトのDOM構造を把握して、最短ルートで価格情報にたどり着けるように考えて実装しました。
難しかったですが、この考え方はpuppeteerでなくても、また、JavaScriptでなくてもWEBスクレイピングには共通の考え方だと思うので、今後も役立ちそうな気がします。
実装でこだわったところ
✅ 書籍タイトルがすぐ表示されるようにした
コマンドを実行すると複数のサイトから情報を取ってくる仕様上、どうしても結果が表示されるまでに時間が掛かってしまいます。
やもすれば「ちゃんと実行できてないのかな?」と使用者が心配になってしまうかもしれないと思ったので、ISBNの入力がされたら、書籍名だけはすぐに表示されるようにしました。
正しい書籍名が表示されれば、「ちゃんと実行できていそうだな」と感じられますし、ISBNが正しいということもすぐに確認ができるからです。
ちなみに書籍名は、openBDが提供しているAPIを叩いて取得しています。
✅ URLを表示してすぐアクセスできるようにした
価格情報だけだと、実際に購入する際に改めて自分でブラウザを立ち上げて書籍を検索して…という手間がかかります。
この手間を省くために、価格情報と一緒に指定した書籍の販売ページのURLも併記するようにしました。
✅ 取り扱いがないサイトはその旨表示するようにした
販売サイトによって、取り扱いのない書籍もあります。
その場合に、そもそもその販売サイトの表示をしない仕様も考えたのですが、個人的には「取り扱いがない」というのも割と知りたい情報だと思いました。
ですので、取り扱いがなければ「取り扱いがありません」という表示をして視覚的にわかるようにしました。
雑感
npmの公開は、フィヨルドの課題で取り組んだものではありますが、これまでの課題とは
- 仕様を自分で考える必要がある
- 明確な答えが存在しない
- 全世界に公開するもの
といったところが違いました。
実際に自分がエンジニアになったら、もっと高いレベルで利用者のことを考えたり、少しでも使いやすくと工夫したり、より価値の高い体験を提供できるよう機能を拡張したりといったことをするのだと思います。 今回のnpmに関しても、公開することは目的ではなく手段であり、本来の目的は「これを使う誰かの課題を解決すること」だと思うので、そのような視座を多少なりとも持つことができたのが1番の収穫だと感じています。
あとは、このようにちゃんと形にしたものを公開するというのは緊張しますが、とてもやりがいがありますし純粋に楽しいです。
今後の課題
npmに公開はしたものの、まだまだ課題はあります。
それらの課題は、今後WEBサービスとして進化させるときに盛り込んでいけたらと考えています。
その時のために、既知の課題を書き出しておこうと思います。
✅ 対応販売サイトを増やす
現在3サイトのみに対応していますが、他にも書籍販売サイトはたくさんあります。
また、新品だけでなく中古を扱っている場合もあります。
その辺をいい感じに吸収して、利用者個々人にとって使いやすいようにしたいなと思っています。
✅ ポイント値引きに対応する
どこのサイトも定期的にセールをやってたりしていて、単純に値引きされるケースには対応していますが、ポイント還元には対応できていません。
ポイント還元がある場合には、実質金額を表示するなどして比較しやすいようにしたいです。
✅ 書籍名での検索に対応する
現状はISBNによる検索しかできません。
これだと、「いったんISBNを調べてからコマンドを実行する」というなんとも面倒な感じです。
書籍名やワード検索に対応すれば、例えば「Rubyに関する本で安い本はどれかな」「Railsに関する本ってどんなのがあるのかな」といった探し方もできるのではないかと考えています。
✅ Kindle版と単行本版をそれぞれ取得する
最近は、どの書籍もKindle版と単行本版があることが多いです。
さらには、両者で価格が違ったりします。
この辺の扱いもどうしようか模索中です。
WEBサービスになれば、いい感じに両方を表示することが可能かなとふんわり考えています。
✅ 名前をイケてる感じにしたい
「cheapest-books」という名前、ダサい。
英語的に合ってるのかわかりませんが、「チープ」という言葉の響きも、日本人的にはマイナスなイメージがある気もするし、著者へのリスペクトにも欠ける気がする(個人的な感覚です)ので、変えたいと思っています。
WEBサービスとして公開できるまでにはまだ時間が掛かると思うので、良い名前募集中です!!!
まとめ
とても小さいアプリではありますが、アイディアから仕様まで自分で考えて、考えたものを形にするというのはとても良い経験になりました。
与えられた課題を解く、というのとはまた違った難しさがありました。
一方で、せっかく作ったアプリなので、「多くの人に使ってもらいたいなぁ」という気持ちも強く芽生えました。
多くの人に使ってもらうためには、それだけ提供できる価値を備えていなければならないし、価値があっても認知してもらえなければ使ってはもらえません。
そういったところにも視点を向けられるようにならなければいけないとも感じました。
いずれにしても、こうやってアプリを作ったりするのは本当に楽しいしもっともっとやっていきたい。
楽しむことを忘れずに、今後もプログラミングしていきたいと思います。