質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.98%

楽天市場からスクレイピングでデータを自動取得したいです。そのあとCSVに保存。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,099

menuett

score 9

Pythonスクレイピングで楽天市場から商品レビューと参考になった人数を自動で取得しようとしています。
以前はPhantomJSを使っていたのですが、seleniumでのサポートが終わったのでheadless Chromeで代用しようとしています。
やっている流れ
1.楽天市場のレビューを取得したいページに行きます。
2.そのページのURLをコピーします。
3.pageはページ数で最初は1にしておきます。pathは楽天レビューの「次の15件」のボタンのXpathです。
4.「次の15件」がそのページにあったらループ、なかったらbreakです
※なぜか「次の15件」のXpathが最初のページ以外違ったので、最後の方でpathを更新しています。
5.CSVに保存します。
csvには、参考になった人数,レビュー本文といった形式で保存します。
※参考になった人数が空の場合は0とする。
実行すると1ページ目はうまく取得できるのですが、2ページ目以降になると取得できません。
Pythonのバージョンは3.6.5です。
Windouws10,jupyter notebookで作成しました。


実行結果
---------------------------page: 1 -----------------------------

Starting to get reviews...

score                                               text
0     39  この商品は色違いで3点目の購入です。今回はブラックを購入しました。\nよく伸びるので曲げ伸ば...
1     23  2016年10月にツイル&デニムのL、11月にデニムLLを。ツイル(ボルドー)は着衣の繊維が...
2     19  ずっと気になっていてやっと買えました。\n2592円(税抜)が24時間限定50%ポイント還元...
3      6  今年の冬は特に寒かったけどこのパンツで温かく過ごせました。何本も購入したのでほぼ毎日のように...
4      9  この冬大活躍しました。\n結局何回もリピ買いして計6本。穿くときのヒヤッと感が無いのも◎だし...
5      6  167cm、56kgでお肉は下半身に付く方です。\n以前ボルドーのLを購入してウェストも丈も...
6      6  レビューがいいので安心して購入しました。\n155センチ48キロ、サイズはSかMで、モノによ...
7      6  裏フリースの物を買っといてなんですが、あんまり足が太く見えたら嫌だなぁ~と思いワインのSサイ...
8      4  ⇒身長163cm 体重55kgでLを選びました。\n最初はMをお願いしたのですが、\nウエス...
9      4  本日届きました。\nレビューを見ると 「サイズにばらつきが有る」「生地が伸びる 伸びない」不...
10     4  165センチ、48キロ。普段のパンツはMで、ベージュとオリーブのMを購入。暖かいのに、シルエ...
11     3  161センチ52キロでMサイズを購入しました。\n骨盤が張っていてお尻も大きく太ももも太めな...
12     3  170cm55キロ、お尻が大き目なのでサイズLを購入。\nコーデュロイ ブラックです。\nス...
13     4  2018verのツイルの黒を購入しました。2年前に買ったMはちょうど良かったのですが、今回の...
14     3  168cm、55kg、トップスはM、ボトムスは物によりけりで、デニムは普段24インチです。\...
next url:https://review.rakuten.co.jp/item/1/200612_10056893/2.1/
Moving to next page......

---------------------------page: 2 -----------------------------

Starting to get reviews...

NoSuchElementException                    Traceback (most recent call last)
#追加部分↓
<ipython-input-14-43bd36a04d9d> in <module>()
25     #dfつくる
26     for review in reviews:
---> 27         score=review.find_element_by_css_selector("span.revEntryAnsNum").text
28         text=review.find_element_by_css_selector("dd.revRvwUserEntryCmt.description").text
29         se=pd.Series([score,text],columns)

~\Anaconda3\lib\site-packages\selenium\webdriver\remote\webelement.py in find_element_by_css_selector(self, css_selector)
428             element = element.find_element_by_css_selector('#foo')
429         """
--> 430         return self.find_element(by=By.CSS_SELECTOR, value=css_selector)
431 
432     def find_elements_by_css_selector(self, css_selector):

~\Anaconda3\lib\site-packages\selenium\webdriver\remote\webelement.py in find_element(self, by, value)
657 
658         return self._execute(Command.FIND_CHILD_ELEMENT,
--> 659                              {"using": by, "value": value})['value']
660 
661     def find_elements(self, by=By.ID, value=None):

~\Anaconda3\lib\site-packages\selenium\webdriver\remote\webelement.py in _execute(self, command, params)
631             params = {}
632         params['id'] = self._id
--> 633         return self._parent.execute(command, params)
634 
635     def find_element(self, by=By.ID, value=None):

~\Anaconda3\lib\site-packages\selenium\webdriver\remote\webdriver.py in execute(self, driver_command, params)
319         response = self.command_executor.execute(driver_command, params)
320         if response:
--> 321             self.error_handler.check_response(response)
322             response['value'] = self._unwrap_value(
323                 response.get('value', None))

~\Anaconda3\lib\site-packages\selenium\webdriver\remote\errorhandler.py in check_response(self, response)
240                 alert_text = value['alert'].get('text')
241             raise exception_class(message, screen, stacktrace, alert_text)
--> 242         raise exception_class(message, screen, stacktrace)
243 
244     def _value_or_default(self, obj, key, default):

NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"span.revEntryAnsNum"}
(Session info: headless chrome=70.0.3538.110)
(Driver info: chromedriver=2.44.609538 (b655c5a60b0b544917107a59d4153d4bf78e1b90),platform=Windows NT 10.0.17134 x86_64)

このように2ページ目以降は取得できません。 この状況の解決方法を教えていただきたいです。  よろしくお願いします。

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import chromedriver_binary
import pandas as pd
import time

options = Options()
options.add_argument('--headless')
driver = webdriver.Chrome(options=options)
url="https://review.rakuten.co.jp/item/1/200612_10056893/1.1/" #URLをはる
driver.get(url)
page=1
columns=["score","text"] #列の作成
df=pd.DataFrame(columns=columns)
path="//*[@id='revRvwSec']/div[1]/div/div[3]/div[16]/div/div/a[5]"

while True:
    print(" ")
    print("---------------------------page: {} -----------------------------".format(page))
    print(" ")
    print("Starting to get reviews...")
    print(" ")
    reviews=driver.find_elements_by_css_selector("div.revRvwUserMain")
    #dfつくる
    for review in reviews:
        score=review.find_element_by_css_selector("span.revEntryAnsNum").text
        text=review.find_element_by_css_selector("dd.revRvwUserEntryCmt.description").text
        se=pd.Series([score,text],columns)
        df=df.append(se,columns)
    print(df)

    if len(driver.find_elements_by_xpath(path))>0:
        next_page=driver.find_element_by_xpath(path).get_attribute("href")
        print("next url:{}".format(next_page))
        driver.get(next_page)
        page+=1
        driver.implicitly_wait(10)
        print("Moving to next page......")
        time.sleep(10)
        path="//*[@id='revRvwSec']/div[1]/div/div[2]/div[16]/div/div/a[6]" #「次の15件」のXpathが最初のページ以外違ったので、最後の行でpathを更新しています。
    else:
        break
#CSVに保存
print(" ")
print("Saving as csv.....")
print("")
df.to_csv("review.csv", encoding = 'utf_8_sig')
print("Processing Exit")
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Lhankor_Mhy

    2018/12/04 20:49

    エラーメッセージはそれだけですか?

    キャンセル

  • menuett

    2018/12/04 21:19

    いいえ 質問が見づらくなると考え省略しました。編集で追加しておきます。

    キャンセル

回答 1

checkベストアンサー

+1

span.revEntryAnsNumが存在しない、というエラーだと思います。
そこで、https://review.rakuten.co.jp/item/1/200612_10056893/2.1/を見てみたところ、みくりや。さんのレビューにはspan.revEntryAnsNumがありませんでした。

ですので、

1ページ目はうまく取得できるのですが、2ページ目以降になると取得できません。

というのは、ご質問者の勘違いで、ページ数とは全然関係がなく「1ページ目はたまたまうまく取得できていた」というのが正しいようです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/05 16:03

    回答ありがとうございます。
    try:
    score=review.find_element_by_css_selector("span.revEntryAnsNum").text
    except:
    score = "0"
    とすることで参考になった人数は0人ということでレビューデータが取得できました。
    レビューデータが膨大なのでスクレイピングの時間がかかるのが面倒ですが、
    ゆっくり待ちます。ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.98%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる