PythonでAmazon Kindleの書籍をWebスクレイピング

Photo by Markus Spiske
Photo by Markus Spiske on Pexels.com

こんにちは ぼお です❗

今回はPythonでできることの目玉の一つである
『Webスクレイピング』を紹介します。

Webスクレイピングとは

ぼお
ぼお

『Webスクレイピング』って何やねん?!

ぼぉ
ぼぉ

Webページの内容をいただくことだよん!

Webスクレイピングを行うと
わざわざWebブラウザを開いて
ユーザID,パスワードを入力して・・・
といった一連の操作を行わなくても
自動でWebページの内容を取ってきて
例えばメールに送信したりする
ということができます。

この記事では、実際にWebスクレイピングで
Amazon Kindleのページのデータを
取ってきて表示する
というプログラムの公開と簡単な解説をします。

この記事の目的とやらなくて良いこと

この記事は、
これだけのプログラムを作るだけでも
こんなことができてしまう
ということを説明するためのもの
です。

そのため、プログラムの中身を
隅から隅まで理解してもらう
ことは目的としていませんし、
隅から隅まで理解してもらう必要も
ない
のです。

後ろを
流し読み程度で見ていただけたら十分
です。

というのも、難しく見えている部分の
大半が
だれかが作った関数の呼び出し
KindleのWebページのHTMLの中身
で、この場でしか通用しないからです。

これらは、プログラムを作るときに
調べて動くように組み合わせて
作り上げていくときにだけ
理解が必要となるものです。
つまり、
今理解するべき内容ではない
のです。

それでも他でも使うから
というのでしたら
プログラムとして、
あるいはメモ書きに
覚えさせておけば良いと思います。

実行結果の動画

作成したWebスクレイピングの
プログラムを実行した動画です。
Visual Studio Codeでプログラムを
開いているところから実行しています。

プログラムは一見すると長そうですが、
実はコメントが多いのと、
同じようなことを繰り返すだけの行が多くて、
後述の図を見ると良いのですが、
何も複雑ではありません。

AmazonのWebページにログインして、
最初はAmazonの注文履歴ページに行きます(^o^;)が
そこからさらにKindleのページに飛び、
1ページ目と2ページ目があり、
そこから情報を取り出しています。

なお、動画では、 Visual Studio Code の上から
実行していますが、
コマンドプロンプトから『python kindle.py』
としても実行できます

また、現在はパソコン上で実行しないと
いけないわけですが、
定期的にkindleにログインして情報を取り出して
ログアウトするようにプログラムを改良しておき、
レンタルサーバ上で動かせば、
完全に自動化することができます。

前提

この記事は Windows 10上で、
Python3 を Anaconda 環境上で使う
ことを前提に書いています。

OS: Windows 10 20H2 (OSビルド 19042.804)
Python 3.8.3

プログラム作成前の準備

Pythonのインストール

まずは、pythonのインストール等が終わっていない場合は、
【第2回】pythonのプログラミング環境を作る
を参照して、 Anaconda 環境をインストールしてください。

必要なPythonモジュールのインストール

Anaconda Powershell Prompt上で
以下のコマンドを実行して
Webの自動操作とHTML解析をする
Pythonモジュールをインストールしてください。

conda install bs4
conda install selenium

Google Chromeをインストール

今回の記事ではウェブブラウザの
Google Chromeが必要になりますので、
こちらからインストールしてください。

Chrome Driverをインストール

“Chrome Driver”というWebドライバが必要です。
こちらから入手してください。

下記画面になるので、『Latest stable release』
を選択してください。

Windows版を選択してください。

以下のように『ダウンロード』の下に
通常はダウンロードされます。
これをダブルクリックか右クリックして
解凍してください。

『chromedriver.exe』ができますので、
例えば、”C:\Program Files (x86)”など、
どこか管理しやすい場所に移動してください。

Amazonのアカウントを準備する

すでにAmazonのアカウントを持っている場合は、
E-mail, パスワードを見れるように準備してください。
まだAmazonのアカウントを持っていない場合は、
こちらからアカウントの登録が必要です。

プログラムの入力

小生と全く同じことをする場合、
Visual Studio Codeのインストール
日本語への設定、ほかいくつか設定
が必要になりますが、セットアップが大変です。

インストールなしで使えるメモ帳(notepoad)か、
インストールだけでOKのサクラエディタを使ってください。

以下にプログラムを掲載します。
メモ帳やサクラエディタを起動して、
以下のプログラムを入力したあと、
青背景のここを変更の部分を変更して、
kindle.pyというファイル名で保存してください。

[kindle.py]

from selenium import webdriver  # seleniumパッケージからWebブラウザ自動操作モジュール
                                # webdriverをインポートする
from bs4 import BeautifulSoup   # bs4パッケージからHTLML解析を行うBeautifulSoup
                                # モジュールをインポートする
import time  # time.sleep()で時間待ちするためだけにtimeモジュールをインポートする

wait_time = 30 # 各Web操作での最大の待ち時間
wait_time_login = 3 # の固定の待ち時間

# Google ChromeのWebドライバを起動する
driver = webdriver.Chrome('ここを変更')
driver.implicitly_wait(wait_time) # 各Web操作での最大の待ち時間を設定

# Amazonのログインページに飛ぶ
driver.get("https://www.amazon.co.jp/ap/signin?_encoding=UTF8&accountStatusPolicy=P1&openid.assoc_handle=jpflex&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.mode=checkid_setup&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0&openid.ns.pape=http%3A%2F%2Fspecs.openid.net%2Fextensions%2Fpape%2F1.0&openid.pape.max_auth_age=0&openid.return_to=https%3A%2F%2Fwww.amazon.co.jp%2Fgp%2Fyour-account%2Forder-history%3Fie%3DUTF8%26digitalOrders%3D1%26opt%3Dab%26orderFilter%3Dyear-2018%26returnTo%3D%26unifiedOrders%3D1&pageId=webcs-yourorder&showRmrMe=1")

# E-mailアドレスを入力する
email_elem = driver.find_element_by_id("ap_email") # 入力欄を見つける
email_elem.send_keys("ここを変更") # E-mailアドレスを入力する
email_elem.submit() # ボタンを押す(送信)

# パスワードを入力する
password_elem = driver.find_element_by_id("ap_password") # 入力欄を見つける
password_elem.send_keys("ここを変更") # パスワードを入力する
password_elem.submit() # ボタンを押す(送信)

time.sleep(wait_time_login) # もっといい方法がないか今後見つけたい

page = 1 # Amazon新着ページの表示ページを1ページ目から開始する


while True:
    # Amazon新着ページのURL(ページ番号付き)
    url = "https://www.amazon.co.jp/gp/bestsellers/digital-text/" \
            f"4897508051/ref=zg_bs_pg_1?ie=UTF8&pg={page}"

    ret = driver.get(url) # Amazon新着ページに飛ぶ

    # ページの内容をHTMLとして解析しておいしいスープを作る
    soup = BeautifulSoup(driver.page_source,"html.parser")

    # スープの中から新着本の一覧を一挙に取り出してelems(要素群)とする
    elems = soup.find_all(class_="zg-item")

    if len(elems) == 0 :
        # 『ページが見つからなかった』ページが表示されたと判斷する
        break

    # 要素群から1つ1つ要素(elem)を取り出してループする
    for elem in elems:
        # 商品によってデータが無い部分があるので予め初期化
        img_link = ''
        book_title = ''
        book_link = ''
        star = ''
        author = ''
        author_link = ''
        review_num = ''
        review_link = ''
        version = ''
        price = ''

        # 商品のデータを取り出す
        # 商品によってデータが無い部分があるので ひたすらtryして
        # なかったら(AttributeErrorなら)、パス(pass)する
        # 実はもっとスマートな方法があるのですが、
# 説明が難しくなるのでやめます try: # 次に見つかった<img>タグのsrc属性を取り出す img_link = elem.find_next("img").get("src") except AttributeError: # データ(属性=Attribute)のないものだった pass try: # 次に見つかったp13s-... クラスの<div>タグで
# 囲んだテキストを取り出す book_title = elem.find_next("div", \
class_="p13n-sc-truncate-desktop-type2 p13n-sc-truncated").text except AttributeError: # データ(属性=Attribute)のないものだった pass try: # 次に見つかったa-link-normalクラスの<a>タグ
# のhref(参照URL)を取り出す book_link = elem.find_next("a",
class_="a-link-normal").get("href") except AttributeError: # データ(属性=Attribute)のないものだった pass try: # 次に見つかったa-icon-altクラスの<span>タグ
# で囲んだテキストを取り出す star = elem.find_next("span",
class_="a-icon-alt").text except AttributeError: # データ(属性=Attribute)のないものだった pass try: # 次に見つかったa-size-small ...クラスの<a>タグ
# で囲んだテキストを取り出す author = elem.find_next("a",
class_="a-size-small a-link-child").text except AttributeError: # データ(属性=Attribute)のないものだった pass try: # 次に見つかったa-size-small ...クラスの<a>タグ
# のhref(参照)を取り出す author_link = elem.find_next("a",
class_="a-size-small a-link-child").get("href") except AttributeError: # データ(属性=Attribute)のないものだった pass try: # 次に見つかったa-size-small ...クラスの<a>タグ
# で囲んだテキストを取り出す review_num = elem.find_next("a",
class_="a-size-small a-link-normal").text except AttributeError: # データ(属性=Attribute)のないものだった pass try: # 次に見つかったa-size-small ...クラスの<a>タグ
# のhref(参照)を取り出す review_link = elem.find_next("a",
class_="a-size-small a-link-normal").get("href") except AttributeError: # データ(属性=Attribute)のないものだった pass try: # 次に見つかったa-size-small ...クラスの
# <span>タグで囲んだテキストを取り出す version = elem.find_next("span",
class_="a-size-small a-color-secondary").text except AttributeError: # データ(属性=Attribute)のないものだった pass try: # 次に見つかったp13n-sc-priceクラスの
# <span>タグで囲んだテキストを取り出す price = elem.find_next("span",
class_="p13n-sc-price").text except AttributeError: # データ(属性=Attribute)のないものだった pass # さあ表示しましょう print("------------------------------------------------------") print('タイトル:' + book_title) print('リンク:' + book_link) print('画像:' + img_link) print('評価:' + star) print('著者:' + author) print('著者リンク:' + author_link) print('レビュー数:' + review_num) print('レビューリンク:' + review_link) print('版:' + version) print('価格:' + price) print("-----------------------------------------------------") page += 1 # Amazon新着ページの表示ページを1つ進める

プログラムの実行

Anaconda Powershell Prompt を起動して
kindle.pyを保存したフォルダに下記の通り
“cd”コマンドで移動して、
“python kindle.py”と入力してください。

cd <kindle.pyを保存したフォルダ>
python kindle.py

プログラムの簡単解説

プログラムは作り上げるまでに
構造を理解しながら作成し
何度も試行錯誤して修正するので、

構造がわかっていないし
苦労の経緯も知らない人が
いきなり見させられると、
苦痛に感じる思います。
これは小生とて同じです。

ですので、
大きく構造がどうなっているかを捉えて
細かいところはあとから追々理解すれば
良いと思います。
細かいことはコメントに書いていますので・・・

ということで構造は以下のとおりです。
2回ループして、2箇所に条件分岐がありますが、
それ以外は、淡々とやることをこなしているだけです。

Google ChromeのWebドライバを起動する だの
スープを作る だの というところは、
ググって取ってきて貼り付けて
前後のつじつま合わせをしているだけです。😂

そして、上図の一番最後から上に向かって
必要な処理は何か?を組み立てているだけです。
『次のページにする』には『要素がなくなる』ことが必要
『タイトル、著者などズバババッと表示する』には
『タイトル、著者など具材(要素)を見つける』ことが必要
・・・
といった具合にです。

以下は、Amazon新着ページの
書籍一覧部分のHTML構造です。


<span class="aok-inline-block zg-item">
    <a class="a-link-normal" target="_blank" href="hoge">
        <span class="zg-text-center-align">
            <div class="a-section a-spacing-small">
                <img alt="この世界の片隅に : 上 (アクションコミックス)" src="hoge.jpg"
                    height="200" width="200">
            </div>
        </span>
        <div class="p13n-sc-truncate-desktop-type2 p13n-sc-truncated"
            aria-hidden="true" data-rows="1" data-truncate-by-character="1">
            この世界の片隅に : 上 (アクションコミックス)
        </div>
    </a>
    <div class="a-row a-size-small">
        <a class="a-size-small a-link-child" href="hoge">
            こうの史代
        </a>
    </div>
    <div class="a-icon-row a-spacing-none">
        <a class="a-link-normal" title="5つ星のうち 4.6" href="hoge">
            <i class="a-icon a-icon-star a-star-4-5 aok-align-top">
                <span class="a-icon-alt">
                    5つ星のうち 4.6
                </span>
            </i>
        </a>
        <a class="a-size-small a-link-normal" href="hoge">
            369
        </a>
    </div>
    <div class="a-row a-size-small">
        <span class="a-size-small a-color-secondary">
            Kindle版
        </span>
    </div>
    <div class="a-row">
        <a class="a-link-normal a-text-normal" target="_blank" href="hoge">
            <span class="a-size-base a-color-price">
                <span class="p13n-sc-price">
                    ¥99
                </span>
            </span>
        </a>
    </div>
</span>

これは、Google Chromeの
とある機能を使うと簡単に取り出せます。

この構造を見ないと、
青背景の部分の”zg-item”というHTMLタグや、

”p13n-sc-truncate-desktop-type2 p13n-sc-truncated”
というクラス(class)のテキスト部分
”この世界の片隅に : 上 (アクションコミックス)”

を見つける
ことができません。

実は今回、下記のHTMLを取ってきて、コピーして
不要なところを削除することで
プログラムの大半を作成したのです!😂

まとめ

いかがでしたでしょうか。
難しいでしょうか。
見た目が難しいだけだと
考えてもらえればOKです。

作っているときは
つまずきが何度もありながらも
負けるものか❗️ という思いと
動いたときの幸福感の両方で夢中になり
最終的にはそんなに難しいとは
思わないのですよ。

プログラム自体はたぶん10時間で
できてしまってます。
ただし、これは、前回、別のyahooの
サイト向けに作った初回作の時間を
足していますので、今回だけにかかった
時間は4時間だけ
です。

一番時間がかかったのは
この記事のほうでした
❗️😂
はじめて使った動画ソフトでモザイクも
かけないといけないし、記事自体も何度も
読み直しと訂正をして18時間❗️

ということで、プログラムよりも
動画と記事の作成のほうが
使いまわしができないし
難しい

ということがわかりました。

では、また次回は改良されることを
乞うご期待❗️

#python #Webスクレイピング #BeautifulSoup #selenium #Kindle

タイトルとURLをコピーしました