Pythonでレビュー探偵をスクレイピングする【Amazon】

Pythonでレビュー探偵をスクレイピングする【Amazon】 プログラミング

レビュー探偵を利用していますか?
サクラチェッカーの勢いに押されている感はありますね。

個人的には、両方を使えばよいと思います。
どんなことでも、一つを盲目的に信用するのは危険ですから。

ただ、2つを使う手間は避けたいです。
そこで、1度に両方を利用したいと考えました。

そのためには、両方のサイトをスクレイピングすればいいのです。
同じ画面内にサクラチェッカーとレビュー探偵の結果が出れば、便利だと思いませんか?
便利ですし、時間の短縮になります。

ということで、レビュー探偵をスクレイピングします。
この記事では、その方法を解説していきます。

本記事の内容

  • レビュー探偵から欲しい情報
  • レビュー探偵のスクレイピング仕様
  • レビュー探偵からスクレイピングでデータを取得する
  • Pythonで レビュー探偵をスクレイピングするのまとめ

なお、サクラチェッカーをスクレイピングする方法は、次の記事で解説しています。

それでは、まずはレビュー探偵からどのような情報を取得するのかを決めます。
要件定義みたいなものですね。

レビュー探偵から欲しい情報

サクラチェッカー同様に、商品の「真の評価」が取得したい情報です。
それが、レビュー探偵に存在している前提で話を進めます。

存在すると言っても、結局はレビュー探偵の開発者の恣意的な判断は入ります。
独自の評価をしている以上は、独自の判断基準があるはずです。

「それが単なるプログラムのロジックなのか?」
「それとも機械学習のモデルなのか?」
これについては、わかりません。

しかし、レビュー探偵独自の評価はAmazonの評価よりも信用できます。
これは事実でしょう。

だからこそ、多くの人々がレビュー探偵を利用しています。
これは、サクラチェッカーも同じです。

そして、先ほどから出ている独自の評価が欲しい情報となります。
詳細に関しては、後述のスクレイピング仕様で説明します。

さて、記事内で扱う商品を説明しておきます。
Amazonの評価とレビュー探偵の評価を比較するために取り扱います。

Amazonでの商品URLは以下
https://www.amazon.co.jp/dp/B07Z1XXVJT/

Amazonカスタマーレビュー

2020年7月6日時点の評価です。
そこそこ評価の高い商品ですね。
何も知らないと、格安でこの評価なら購入してしまうかもしれません。

レビュー探偵のスクレイピング仕様

詳細ページURL

商品に対する評価は、次のページで取得できます。
https://review-tantei.com/detail/B07Z1XXVJT/

「B07Z1XXVJT」は、ASIN番号です。
ASIN番号は、「Amazon Standard Identification Number」の略となります。
よって、ASINを変更すれば、レビュー探偵内の商品評価のページになるということです。

これは、サクラチェッカーと同じですね。
それ以外の、海外の評価サイトも同じような形式です。
これは、Amazonチェッカー業界の常識なのでしょう。

ASINというワードが、先ほどから何回も出ています。
「ASINをどうやって知るのか?」と思う人もいるはずです。

これは、Amazonの商品ページに記載されています。
よって、その商品ページをスクレイピングしてASINを取得します。

「おいおい、Amazonはスクレイピングが禁止だよ!!」
このように思う方もいるかもしれません。
そのような方は、次の記事をご覧ください。

結論としては、Amazonはスクレイピング禁止ではありません。
正確には、禁止ではない状況があります。

それは、ログインしていない場合です。
このあたりを上の記事では、詳しく説明しています。

少し話がズレましたので、ASINに話を戻します。
ASINを知る術は、以下の方法となります。

  1. Amazonの商品URLを入力
  2. 商品URLをもとにAmazonをスクレイピングしてASINを取得

取得できたASINをもとに次のURLを作成します。
https://review-tantei.com/detail/取得したASIN/

取得するデータ

独自の評価

レビュー探偵の評価

「1.1」は、レビュー探偵が下した評価です。
Amazonの3.9からは、かなり落ちますね。

この独自の評価が、レビュー探偵で最重要のデータとなります。
レビュー探偵は、静的コンテンツで評価が表示されています。

<div class="d new_review_rating" style=" width: 40%;">
    <h4>レビュー調査後</h4>
    <div class="star-rating">

        <div class="star-rating-front" style="width: 22%">
            ★★★★★                                    </div>
        <div class="star-rating-back">
            ★★★★★                                    </div>
    </div>
    <strong class="text-danger">★1.1</strong>

</div>

サクラチェッカーは、動的コンテンツとして表示する形式です。
そのため、Seleniumを利用してスクレイピングしています。

よって、レビュー探偵の方がスクレイピングはやりやすそうです。
しかし、HTMLの構造が素直ではありませんね。

<strong class="text-danger">★1.1</strong>

上記の「.text-danger」は、複数存在することがありえます。
また、「.text-danger」は、評価の値に連動しています。

危険水域の評価だから、「.text-danger」になるようです。
そのため、「.text-secondary」になる場合もあるようです。

そうであれば、クラス名指定でスクレイピングするのは無理ですね。
「.new_review_rating」div要素内のstrongタグで指定する形になります。
若干、違和感の残るHTML構造です。

レビューの信用度と判定結果

レビュー探偵の信頼度

レビュー探偵では、「レビューの信用度」という表記です。
サクラチェッカーの「サクラ度」と似たようなモノでしょうね。

「サクラ度」はサクラが含まれている比率を表現しています。
「レビューの信用度」は「サクラ度」を100からマイナスしたと言えるでしょう。

つまり、極端に表現すると以下の計算式です。

レビュー信用度 = 100 - サクラ度

もちろん、両方のサービスに直接の関係はないです。
そのため、上の計算式が成立することはあり得ません。
あくまで、理解の助けになると考えての計算式です。

HTMLの構成を確認しましょう。
やはり、個人的には違和感がありますね。
スクレイピング対策としてやっているなら、有効なコーディングだとは思います。

<div class="detail-el detail-el-trust">
    <div class="trust_score">
        レビューの信用度は
        <strong class="text-danger">
            1%                        </strong>
        です
    </div>

    <div class="progress">
        <div class="progress-bar progress-bar-striped bg-danger"
           role="progressbar" style="width: 1%"
           aria-valuenow="1"
           aria-valuemin="0"
           aria-valuemax="100"
        >1%</div>
    </div>

    <div class="trust_grade">
        判定結果
        <strong class="text-danger">
            F 最低                        </strong>
    </div>
    <p class="trust_comment">
        レビューの判定結果としては最も疑わしい判定です。特別な理由がない限り、レビュー自体は信用しないほうがよさそうです。                    </p>

</div>

独自の評価をスクレイピングする場合と同じ考え方です。
まずは、「.detail-el-trust」div要素を抽出しておきます。

レビューの信用度は、抽出した要素内で「.trust_score」div要素内のstrongタグを指定します。
また、判定結果は、抽出した要素内で「.trust_score」div要素内のstrongタグを指定します。

違和感の残るHTML構造ですが、コーディングのやり方は統一されています。
その点では、まだスクレイピングはやりやすいと言えますね。

なお、判定結果は数値化します。
数値化しておいた方がなにかと都合が良いです。

例えば、機械学習を行う場合です。
もともと数値であれば、ダミー変数を用意する必要がありません。

SABCDEF
7654321

レビュー評価詳細

レビュー探偵のレビュー評価詳細

評価の項目となります。
商品購入時には、そこま必要なデータではありません。
いちいち見るのは面倒です。

しかし、レビュー探偵の評価ロジック(プログラム?機械学習のモデル?)を紐解くヒントになる情報です。
よって、これらもスクレイピングしておきましょう。

評価は、4パターン存在しています。
それらはクラス名・その数で判断します。

評価(数値化)評価クラス名とその数
1×text-danger
2× ×text-danger text-danger
3text-warning
4text-primary

それぞれの評価項目毎に、上記のクラス名を持つ要素の数で判定できそうです。
なお、評価を数値化しておきます。
これは、判定結果を数値化したのと同じ理由です。

レビュー評価を集計した結果の項目には、「.text-danger」が2つあります。
よって、「× ×」の評価と判断できます。

<li class="list-group-item">
    <i class="fa fa-times fa-fw text-danger"></i>
    <i class="fa fa-times fa-fw text-danger"></i>
    レビュー評価を集計した結果、「やらせ・さくらなどの嘘レビュー」の際と似ている点が、かなり多くあるようです。
    検知されやすさは時期やカテゴリによって変わることがあります。
</li>

購入者が書いたレビューの項目には、「.text-primary」が1つあります。
よって、「○」の評価と判断できます。

<li class="list-group-item">
    <i class="fa fa-circle-o fa-fw text-primary"></i>
    実際の購入者が書いたと思われるレビューの割合は正常です。
</li>

調査日時

レビュー探偵の調査日時

私が確認したときの評価・評価数が、確かに異なります。

確認・調査日時評価評価数
2020-07-06 午前中3.8171
2020-06-21 17:02:103.9149

これは、システム的にリアルタイムの調査・評価は不可ということでしょう。
レビュー探偵のサーバーは、それなりに負荷の高い処理をしているはずです。

  • Amazonへのスクレイピングによりレビューデータ収集
  • 収集したデータをもとに評価(プログラム?機械学習?)

おそらく、これらの処理をサーバーで行なっているのだと思います。
それは、サクラチェッカーも同様でしょう。

調査日時とのタイムラグも認識はしておくべきでしょう。
よって、レビュー探偵が行った調査日時も取得しておきます。

やっと、違和感のないコードです。

<div class="analyzed_at">
    最終調査: 2020-06-21 17:02:10
</div>

「.analyzed_at」が、ページに一つのみ存在しています。
よって、ピンポイントで「.analyzed_at」を指定するだけです。

レビュー探偵からスクレイピングでデータを取得する

必要なライブラリ・モジュールのインストール

pip install requests
pip install beautifulsoup4

検証コード

エラーチェックは、厳しくしていません。
必要なら、適宜対応してください。

import requests
import traceback
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'
}

# ASIN取得
def get_asin_from_amazon(url):
    
    asin = ""
    
    try:
        res = requests.get(url, headers=headers)
        soup = BeautifulSoup(res.content, features='lxml')
        
        div_base = soup.find(class_="column col2")
        asin = div_base.find(class_="value").text
    except:
        print(res)
        traceback.print_exc()        
    
    return asin

# レビュー探偵をスクレイピング
def get_reviewtantei(asin):
    
    url = "https://review-tantei.com/detail/" + asin + "/"
    
    try:
        res = requests.get(url, headers=headers)
        soup = BeautifulSoup(res.content, features='lxml')
        
        # 独自の評価
        div_new_review_rating = soup.find(class_="new_review_rating")
        rating = div_new_review_rating.find("strong").text
        rating = rating.replace("★", "", 1)
        rating = rating.strip()
        
        # レビューの信用度と判定結果
        div_detail_el_trust = soup.find(class_="detail-el-trust")
        
        trust_score = div_detail_el_trust.find(class_="trust_score").find("strong").text
        trust_score = trust_score.replace("%", "", 1)
        trust_score = trust_score.strip()
        
        tmp_trust_grade = div_detail_el_trust.find(class_="trust_grade").find("strong").text
        tmp_trust_grade = tmp_trust_grade.replace("%", "", 1)
        tmp_trust_grade = tmp_trust_grade.strip()
        tmp_trust_grade_list = tmp_trust_grade.split(' ')
        trust_grade = tmp_trust_grade_list[0]
        
        if ('A' in trust_grade):
            trust_grade_2 = 6
        elif ('B' in trust_grade):
            trust_grade_2 = 5
        elif ('C' in trust_grade):
            trust_grade_2 = 4
        elif ('D' in trust_grade):
            trust_grade_2 = 3
        elif ('E' in trust_grade):
            trust_grade_2 = 2
        elif ('F' in trust_grade):
            trust_grade_2 = 1
        elif ('S' in trust_grade):
            trust_grade_2 = 7
        else:
            trust_grade_2 = 0
        
        # レビュー評価詳細
        ul_outer = soup.find(class_="list-group list-group-flush text-left")
        li_list_group_item = ul_outer.find_all(class_="list-group-item")
        
        check = []
        for i in range(len(li_list_group_item)):
            tmp = li_list_group_item[i].find_all(class_="fa")
            
            if len(tmp) == 2:
                # 「× ×」
                check_point = 1
            else:
                target_str = str(tmp[0])


                if ('text-danger' in target_str):
                    # 「×」
                    check_point = 2
                elif ('text-warning' in target_str):
                    # 「!」
                    check_point = 3
                elif ('text-primary' in target_str):
                    # 「○」
                    check_point = 4
                else:
                    check_point = 0
            
            check.append(check_point)
                
        # 最終調査
        analyzed_at = soup.find(class_="analyzed_at").text
        analyzed_at = analyzed_at.replace("最終調査:", "", 1)
        analyzed_at = analyzed_at.strip()

    except:
        print(res)
        traceback.print_exc()         
    
    print("独自評価:" + rating)
    print("レビューの信用度:" + trust_score)
    print("判定結果:" + str(trust_grade_2))
    print("レビュー評価詳細:")
    print(check)
    print("最終調査:" + analyzed_at)
    
if __name__ == '__main__':
    url = 'https://www.amazon.co.jp/Bluetooth-USB%E3%83%AC%E3%82%B7%E3%83%BC%E3%83%90%E3%83%BC%E3%81%AA%E3%81%97-3DPI%E3%83%A2%E3%83%BC%E3%83%89%E9%AB%98%E7%B2%BE%E5%BA%A6-%E3%83%9C%E3%82%BF%E3%83%B3%E3%82%92%E8%AA%BF%E6%95%B4%E5%8F%AF%E8%83%BD-iPad%E6%9C%80%E6%96%B0%E3%81%AEIOS/dp/B07Z1XXVJT/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&amp;dchild=1&amp;keywords=%E3%80%90%E6%8C%87%E7%B4%8B%E9%98%B2%E6%AD%A2%E3%80%91+Bluetooth+%E3%83%9E%E3%82%A6%E3%82%B9+%E9%9D%99%E9%9F%B3+%E8%96%84%E5%9E%8B+USB%E3%83%AC%E3%82%B7%E3%83%BC%E3%83%90%E3%83%BC%E3%81%AA%E3%81%97+%E5%85%85%E9%9B%BB%E5%BC%8F+3DPI%E3%83%A2%E3%83%BC%E3%83%89%E9%AB%98%E7%B2%BE%E5%BA%A6&amp;qid=1593991441&amp;s=computers&amp;sr=1-1'
    
    # 実際にアクセスしてASIN取得
    asin = get_asin_from_amazon(url)
    
    # レビュー探偵をスクレイピング
    get_reviewtantei(asin)

【2020年7月14日追記】
現在このコードは動きません。
Amazonがスクレイピング対策をしてきました。
次の記事でその対策の攻略方法を解説しています。

この検証コードを実行すると、以下の結果となります。

独自評価:1.1
レビューの信用度:1
判定結果:1
レビュー評価詳細:
[1, 2, 4, 3, 4, 1]
最終調査:2020-06-21 17:02:10

「レビュー探偵のスクレイピング仕様」の仕様通りに動いていますね。

やはり、HTML構造に少々クセがあります。
そのため、なかなかスクレイピングがやりにくです。

サクラチェッカーは、Seleniumが必要でした。
しかし、HTML構造はレビュー探偵ほどクセはありません。

トータルでは、サクラチェッカーの方が容易にスクレイピングが可能です。

「Pythonでレビュー探偵をスクレイピングする」のまとめ

Pythonでレビュー探偵をスクレイピングする方法を説明してきました。
どうでしたでしょうか?

レビュー探偵やサクラチェッカーは、Amazonをスクレイピングしています。
これらのサイトは、悪い言い方をすればAmazonの寄生虫です。

そして、私はその寄生虫に寄生します。
やはり、データがネットに公開されている以上はこれは避けられないでしょう

と言っても、個人的にはスクレイピングに依存するのは怖いです。
スクレイピング先のHTML構造が変化すれば、その時点でアウトになります。

デザイン変更なんて、一般的によく行われていますからね。
実際、それで痛い目にあったこともあります。
そのときは、寝ずにスクレイピングのプログラムを修正して対応しました。

デザイン変更ではなく、相手側のバグの影響も受けます。
ここで言うバグは、htmlタグの構成が崩れていることを指します。
とにかく、スクレイピング先に振り回されるのです。

この記事にて、Amazonのレビューチェッカーのスクレイピングは終わりとします。
次は、スクレイピングで収集したデータをもとに自作ツールを作ろうかと思います。
もし、人様にお見せできるようなモノが出来上がれば公開します。

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