こんにちは、カメ助(@kamesuke_blog)です。
最近「スクレイピング」というワードを耳にする機会が増えてきました。
そこで今回はSelenium(セレニウム)を使用したAmazonの商品レビューを「スクレイピング」するプログラムを紹介します。(windows環境)
前半で「スクレイピング」について説明し、後半でサンプルコードを解説します。
この記事はこんな人にオススメ
・「スクレイピング」って何?
・「スクレイピング」のサンプルコードがほしい
皆さんがスクレイピングする際の参考になれば幸いです。
スクレイピングとは
スクレイピングは、ツール・プログラムなどを使って、ウェブサイトから情報を抽出し、利用しやすいように加工することを指します。
ウェブスクレイピング・Webデータ抽出とも言います。
具体的には、
「特定の商品の販売価格を調査するために、Amazonの販売価格の情報を取得し、CSV出力する」
「機械学習の学習データを作成するために画像データを取得する」
などがあります。
スクレイピングの注意点
便利なスクレイピングですが、以下の注意点を守らなければ法律違反で逮捕される可能性があります。
- 対象のウェブサイトがスクレイピングを禁止していないか
- サーバーに過度な負荷をかけていないか
- 取得した情報を情報解析以外に使用しないこと
対象のウェブサイトがスクレイピングを禁止しているかは、利用規約や「robots.txt」、HTML内の「robots metaタグ」で確認できます。
Amazonのスクレイピングについて
今回Amazonの商品レビューをスクレイピングしますが、Amazonの利用規約には以下の記載があり、スクレイピングは禁止されています。
データマイニング、ロボットなどのデータ収集・抽出ツールの使用は、一切含まれません。
Amazonの利用規約より抜粋
この利用規約は、Amazonとお客である(ログインしたユーザー)の間での契約になります。
つまり、Amazonにログインした時点で利用規約に同意したことになるため、ログイン状態(Amazonの利用規約に同意)でのスクレイピングは禁止されています。
逆を言えば、未ログイン状態では利用規約に同意していませんので、利用規約は適用されません。
利用規約に同意していないので当然ですがスクレイピングは禁止されていません。
参考:スクレイピング禁止のAmazonからレビューを抜き出す【Python】
簡潔にまとめると
Amazonに未ログインならスクレイピングはOK
ただし、「短時間に大量のリクエストを送信してサーバーに負荷をかける行為」は法律違反にあたる可能性があるので注意が必要です。
スクレイピングのサンプルコード
スクレイピングのサンプルとして、Amazonの商品レビュー情報をCSVファイルに書き出すコードを紹介します。
処理の流れ
サンプルコードの処理は以下の流れで行います。
- Amazonのサイトにアクセスする
- 商品のレビュー情報を全て取得する
- 取得結果をCSVファイルに出力する
サンプルコードの動作確認環境
Windows環境でPython言語とSeleniumのツールを使用しています。
- OS : Windows10
- 言語 :Python
- ツール :Selenium (chromedriverを使用)
- エディタ :VSCode
- ブラウザ :GoogleChrome
サンプルコード
2021/12/24追記:69行目のコードを変更しました。(open関数の文字エンコードにutf-8を指定)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
from time import sleep from selenium import webdriver from selenium.webdriver.chrome.options import Options from bs4 import BeautifulSoup import textwrap import csv #windows(chromedriver.exeのパスを設定) chrome_path = r'C:\Users\デスクトップ\python\selenium_test\chromedriver' #mac #chrome_path = 'C:/Users/デスクトップ/python/selenium_test/chromedriver' # amazonのレビュー情報をseleniumで取得する_引数:amazonの商品URL def get_amazon_page_info(url): text = "" # 初期化 options = Options() # オプションを用意 options.add_argument('--incognito') # シークレットモードの設定を付与 # chromedriverのパスとパラメータを設定 driver = webdriver.Chrome(executable_path=chrome_path,options=options) driver.get(url) # chromeブラウザでurlを開く driver.implicitly_wait(10) # 指定したドライバの要素が見つかるまでの待ち時間を設定 text = driver.page_source # ページ情報を取得 driver.quit() # chromeブラウザを閉じる return text # 取得したページ情報を返す # 全ページ分をリストにする def get_all_reviews(url): review_list = [] # 初期化 i = 1 # ループ番号の初期化 while True: print(i,'page_search') # 処理状況を表示 i += 1 # ループ番号を更新 text = get_amazon_page_info(url) # amazonの商品ページ情報(HTML)を取得する amazon_bs = BeautifulSoup(text, features='lxml') # HTML情報を解析する reviews = amazon_bs.select('.review-text') # ページ内の全レビューのテキストを取得 for review in reviews: # 取得したレビュー数分だけ処理を繰り返す review_list.append(review) # レビュー情報をreview_listに格納 next_page = amazon_bs.select('li.a-last a') # 「次へ」ボタンの遷移先取得 # 次のページが存在する場合 if next_page != []: # 次のページのURLを生成 next_url = 'https://www.amazon.co.jp/' + next_page[0].attrs['href'] url = next_url # 次のページのURLをセットする sleep(1) # 最低でも1秒は間隔をあける(サーバへ負担がかからないようにする) else: # 次のページが存在しない場合は処理を終了 break return review_list #インポート時は実行されないように記載 if __name__ == '__main__': # Amzon商品ページ url = 'https://www.amazon.co.jp/%E3%83%89%E3%82%A6%E3%82%B7%E3%82%B7%E3%83%A3-%E3%82%BF%E3%83%B3%E3%83%96%E3%83%A9%E3%83%BC-%E7%8C%AB%E8%88%8C%E5%B0%82%E7%A7%91%E3%82%BF%E3%83%B3%E3%83%96%E3%83%A9%E3%83%BC-320ml-%E3%82%B0%E3%83%AA%E3%83%BC%E3%83%B3/dp/B08MW6YQY5/ref=pd_rhf_cr_s_bmx_5?pd_rd_w=1MuoR&pf_rd_p=b35c88ee-075c-481c-ab75-32553855cd5b&pf_rd_r=W5W6QVTMA9PPK89776SH&pd_rd_r=49445fb8-416e-4f67-a3cf-6b650ea6659c&pd_rd_wg=mRwDl&pd_rd_i=B08MW6YQY5&psc=1' # URLをレビューページのものに書き換える review_url = url.replace('dp', 'product-reviews') # レビュー情報の取得 review_list = get_all_reviews(review_url) #CSVにレビュー情報の書き出し #with open('data/sample.csv','w') as f: #Windowsでエンコードエラーになる場合があるため下の行に変更 with open('data/sample.csv','w',encoding='utf-8') as f: writer = csv.writer(f, lineterminator='\n') # 全データを表示 for i in range(len(review_list)): csvlist=[] review_text = textwrap.fill(review_list[i].text, 500) #データ作成 csvlist.append('No.{} : '.format(i+1)) # 便宜上「No.XX」の文字列を作成 csvlist.append(review_text.strip()) # レビューテキストの先頭・末尾の空白文字を除去 # 出力 writer.writerow(csvlist) # ファイルクローズ f.close() |
サンプルコードの詳細については、各行のコメントをご確認ください。
上記サンプルコードはwindows環境用です。
mac環境の方は、以下のようにサンプルを修正してください。
- 9行目の「chrome_path = r’C:\Users\デスクトップ\python\selenium_test\chromedriver’」をコメントアウト
- 12行目の「chrome_path = ‘C:/Users/デスクトップ/python/selenium_test/chromedriver’」をアンコメント
ちなみに上記サンプルは、以下の記事を参考にさせていただきました。
参考:Amazonのスクレイピング対策を攻略する【Selenium最強説】
出力ファイル(一部抜粋)
サンプルコードを実行すると以下のようなCSVファイル(sample.csv)が出力されます。
1 2 3 4 |
No.1 : ,ポットからお湯を入れて、少し待ってからお茶のティーバッグを入れて、蓋をして飲みました。お茶も美味しいし、猫舌でも熱くない!私が持ってる普通タンブラーと比べると重たいけど、それを引いても快適です。1口目が怖くない。 No.2 : ,あと10度は下がってくれないと飲めない。 No.3 : ,猫舌の人用となっていますが、自分の猫舌度ではそれでもアツアツ。3分くらいではまだまだ熱いです、一気に行くのは無謀ってもんです。しっかりと熱いコーヒーが最後の一口までなかなか熱く飲めました。多分入れてから1時間くらいに飲み終わった感じだったと思うけどタンブラー内の温度は温度計で測定したら55度を表示していました。普通の真空ボトルと違うポイントがあり、入れた飲み物の熱を吸収する層があることにより保温がそれなりに続くのだなと思います。ただこれは通勤時に家から入れて持っていくような用途ではなく、家の中で熱い飲み物を入れ家の中で飲み終わるが前提かなと。蓋は付いていますが漏れ防止になっているわけではないので恐らく飲み口周辺から飲み物は漏れると思います。なので通勤時に持っていくとバッグが悲惨な目に合うでしょう。そして何よりも、320mlの容量なのに重い。それも持ち歩くのに向かない一つの要因です。家でPCやりながらゲームをしながらちびちび飲むのにおすすめ。洗うのも非常に楽だしおすすめです。 No.4 : ,ケトルでお湯を沸かしてスティックティーを溶かして、こちらのタンブラーで飲みました。私は相当な猫舌なので、難なく飲めるようになるまで5分くらい要しました。ある一定の温度(60℃くらい)までグッと下がったら、それからは保温されたようにゆっくりと冷めていきます。飲み切るまでにお茶が冷めてしまう、といったことにはなりません。この温度の動きが不思議というか、よくできていると思います。感心しました。容器の開口部から放熱させて飲み物の温度を下げているようです。開口部に触れると、火傷をする程ではないですが熱くなっていました。概ね良い商品ではありますが、2点ほど残念なところがありました。1.食洗器には非対応。2.持ち手のエンボス塗装が温まると少々ベトつき感がある。上記の2点にて星1つ減らして、星4つ評価とします。 |
実際の業務では、出力したCSVファイルの内容を分析していきます。
サンプルコードでエラーが発生した場合の対応策
サンプルコード実行時に遭遇したエラーの原因と解決方法についてまとめておきます。
エラー1:bs4.FeatureNotFound
コンソールに表示されるエラー
1 |
bs4.FeatureNotFound: Couldn't find a tree builder with the features you requested: lxml. Do you need to install a parser library? |
対処方法
コンソールにて、以下のコマンドを実行することでエラーが解消されます。(BeautifulSoupオブジェクトで使用する”lxml”をインストールします。)
1 |
pip3 install lxml |
原因
BeautifulSoupオブジェクトでパーサーのオプションをlxmlに指定していますが、環境にlxmlがインストールされていないことが原因です。
エラー2:FileNotFoundError: [Errno 2] No such file or directory
コンソールに表示されるエラー
1 |
FileNotFoundError: [Errno 2] No such file or directory: 'data/sample.csv' |
対処方法
コンソールにて、以下のコマンドを実行し、カレントディレクトリを変更する。
1 |
cd カレントディレクトリのパス |
原因
ファイルの読込・書込時に対象のファイルやディレクトリが存在しないことが原因です。
今回の場合は、カレントディレクトリ直下に「data/sample.csv」が存在しないためエラーになっています。
エラー3:UnicodeEncodeError
コンソールに表示されるエラー
1 |
UnicodeEncodeError: 'cp932' codec can't encode character '\u203c' in position 17: illegal multibyte sequence |
対処方法
ソースコードを下記のように変更する。
open関数に文字エンコード 【utf-8】を指定しています。※サンプルコードに反映済み
1 2 3 4 |
with open('data/sample.csv','w') as f: ↓ with open('data/sample.csv','w',encoding='utf-8') as f: に変更 |
原因
open関数は文字エンコードが未指定の場合、windows環境ではshift-jisのエンコードで開きます(環境依存のため)。また、python3のプログラム内部では、文字列をutf-8のエンコードで扱っています。
そのため、CSVファイル書き出し時に、文字列データを【utf-8 → shift-jis】に変換しています。 文字列データ に shift-jis に変換できない文字が含まれている場合にエラーが発生します。
参考にさせていただいたページ
まとめ
今回はスクレイピングの説明と、サンプルコードの紹介をしてきました。
スクレイピングを活用することで、効率的に情報収集を行うことが可能になります。そのため、今後より使われる技術ではないかと感じております。
また、スクレイピングは非常に便利ですが、使い方を間違えると法律違反に該当する可能性もありますので注意しましょう。スクレイピングの注意点は以下の通りです。
- 対象のウェブサイトが「スクレイピング」を禁止していないか
- サーバーに過度な負荷をかけていないか
- 取得した情報を情報解析以外に使用しないこと
また、今回のサンプルコードを参考にしていただければ幸いです。
コメント
コメント一覧 (14件)
最近Amazon Web scraping的なキーワードでこのブログに到達して以来スクレイピング系で色々参考にさせていただいています!
ド文系の素人ですがスクレイピングでRPAしたく、こういった記事はとても参考になります!
コメントありがとうございます。
初めてコメントをいただき嬉しかったです!
また役に立つ記事が書けるように頑張りますね!!
突然のコメント欄に質問することを、お許しください。
”カメ助”さんのコードで、スクレピングを勉強している者です。
# 次のページが存在する場合
if next_page != []:
# 次のページのURLを生成
next_url = 'https://www.amazon.co.jp/' + next_page[0].attrs['href']
url = next_url # 次のページのURLをセットする
sleep(1) # 最低でも1秒は間隔をあける(サーバへ負担がかからないようにする)
else: # 次のページが存在しない場合は処理を終了
break
return review_list
実行した所、下記のエラーが表示されました。
”File “”, line 9
break
^
SyntaxError: ‘break’ outside loop”
解決するため、エラー文を翻訳して、Googleで検索等をしてみましたが…自信の理解レベルでは訳分からなくなりましての質問となりました。
ご教授、お願いします。
追伸:環境は、Windows10,ジュピターラボです。
コメントありがとうございます。
>>実行した所、下記のエラーが表示されました。
>>”File “”, line 9
>>break
>>^
>>SyntaxError: ‘break’ outside loop”
→エラーメッセージの内容より、『break』がループ処理の外側に定義されていることが原因である可能性があります。
<確認ポイント>
記事のソースコードでは、33行目の「while True:」でループ処理を開始し、53行目の「break」でループ処理を終了しています。
下記補足より、『break』がwhile文よりもインデント(字下げ)をしているか確認してください。
※ソースコード上のインデントは、タブとスペースを混在しないように注意してください。
(例)タブを使用する場合は、インデントは全てタブで統一してください。
■補足
pythonでは、インデント(字下げ)が意味を持ちますので
下記のパターンAとパターンBでは意味が異なります。
●パターンA ※正しい——
while True:
break
—————–
●パターンB ※エラーになる——
while True:
break
—————–
ご参考にしてください。
また、スクレイピングを勉強される中で「こんなサンプルが欲しい」などありますか?
今後の記事を書く際の参考にさせていただきたいと考えています。
夜分にも拘らずのご教授、ありがとうございます。
未だ、着手しておりませんが、先ずはお礼の一報と思いまして。
ご助言を参考にした所、何とかかんとか…コードは通りました。
ありがとうございます。
その後、残りのコードを実行した所、以下のエラーが出ました。
File “”, line 21
csvlist.append(‘No.{} : ‘.format(i+1)) # 便宜上「No.XX」の文字列を作成
^
SyntaxError: invalid character in identifier
やはり、前回と同じく翻訳をして検索をして…色々試してみましたが…。
例えば、csvlist.append(‘No.{} : ‘.format(i+1))を削除して、直接打ち込んでみたりしましたが…ダメ。
又、No.{} :で、{}と:の間にスペースがあるので、スペースをなくしてみたり…ダメ。
又、検索したサイトで、文字列が識別子として有効かどうかは文字列のメソッドisidentifier()で確認可能とあったので、
print(‘No.{}’.isidentifier())
False
と、出ましたが、その後の対処方法が分かりません。
ご教授、お願い申し上げます
何とか…解決出来ました。
が、新たな問題が発生しました。
自身でもう少し、取り組んでみます。
何とか解決できたようで良かったです。
エラーがあった際は、以下をチェックしてみてください。
■全角で入力している文字列が存在しないかチェックする
■全角空白が混じっていないかチェックする
度々申し訳ございません。
カメ助さんのコードを実行した結果、
1 page_search
2 page_search
3 page_search
4 page_search
5 page_search
6 page_search
7 page_search
8 page_search
9 page_search
10 page_search
—————————————————————————
FileNotFoundError Traceback (most recent call last)
in
67
68 #CSVにレビュー情報の書き出し
—> 69 with open(‘data/sample.csv’,’w’) as f:
70 writer = csv.writer(f, lineterminator=’\n’)
71
FileNotFoundError: [Errno 2] No such file or directory: ‘data/sample.csv’
と、なりました。
私のジュピターラボのデスクトップには、CSVファイルは見当たりません。
又、
import os
os.getcwd()
見ましたが、’data/sample.csv’は、ありません。
何時でもいいので、ご助言お願い致します。
データフォルダを作成して、解決しました。
こんにちは。参考させていただきcsvファイルに書き込んだところ、
テキストが文字化けしてしまいました。
これはAmazon側に対策を取られてしまった結果なのか、
現状サンプルコードで正常にスクレイピング可能かうかがいたく思いました。
連絡ありがとうございます。
<確認結果>
こちらで確認したところ、CSVファイルの中身は文字化けしていないことを確認しました。
<原因>
本サンプルでは、70行目の箇所で文字コードに「utf-8」を指定してCSVファイルを書き出しています。
そのため、「utf-8」以外の文字コードでCSVファイルを開いたために文字化けが起こったと考えられます。
<解決策>
作成したCSVを【サクラエディタ】などのテキストエディタで文字コード「utf-8」で開いていただければ文字化けすることなく内容確認できるかと思います。
一度試していただけますでしょうか。
はじめまして。
こちらのコードを参考に勉強させていただいております。
csvファイルは問題なく書き込みできたのですが、レビューが10件までしか書き込みされていませんでした。
自分のほうでもいろいろいじっては見たのですがわからずじまいで…
解決方法をご教授いただけないでしょうか。
連絡ありがとうございます。
こちらで確認しました。
<原因>
Amazon側でスクレイピング対策を入れていることが原因のようです。
具体的には、seleniumでAmazonにアクセスした際の次ページのレビューリンクが「Amazonのサインインのリンク」になっているため、
次ページのレビューページに遷移できず、先頭ページ分である10レビューしか取得できない状態になっています。
<対応策>
seleniumで次ページのレビューのURLを直接指定する形に変更すれば、次ページ以降のレビュー情報も取得できるかと思います。
※実施は自己責任でお願いいたします。