▼【再改訂版コード】:「R言語」による楽天市場の商品レビューのスクレイピングコードの再改訂版:グラフ作成コードなどを追加:「素焼きアーモンド」の商品レビューのデータを取得:意外と多い「はじめて」の購入
前回の「▼「R言語」による楽天市場の商品レビューのスクレイピングコードの改訂版です:Excelで項目を切り分ける作業が不要になりました」のスクレイピングコードを再改訂しました。ついでに、いくつかの項目のグラフ作成コードを追加しています。▼レビューデータからのグラフ作成 せっかく、レビュー本文のテキスト以外のデータを取得しているので、レビュー内容以外の項目についても、グラフ化しておきたいと思いました。 スクレイピングした項目のグラフを作成しようとして、取り込んだテキストの空白の処理がうまくいっていないことがわかりました。例えば、「購入した回数」の項目で、「リピート」と「はじめて」の件数をグラフにしてみましたが、下図のように酷い状態であることがわかりました(涙)。 どうして、このような「空白」の個体差が生じるのでしょうか。恐らく、「商品の使いみち」「商品を使う人」「購入した回数」を三つすべて回答している場合と、二つ回答、あるいは一つだけ回答という回答の項目数の差によるものではないかと思います。▼前回のコードでのスクレイピングでは、回答項目のテキストに残った「空白」が一定ではありませんでした そこで、各項目のテキストを抽出する際に、「str_trim(., side = "both")」の処理を追加して、テキストの前後の空白を削除するようにしました。ついでに、「{if(length(.) == 0) NA else .}」も入れてみましたが、データフレームの表示では「NA」の表示は見られませんでした。空欄に見えますが、そこには「何か」が潜んでいるのでしょう。 結局、うまくはたらかない「{if(length(.) == 0) NA else .}」は外しました。正規表現とかを的確に使うと何とか「NA」を入れることができるのかもしれませんが、今のところその方法がわかりません。 その後、データをcsvファイルに保存し、そのcsvファイルを読み込む際に、「na.strings=c("","NA")」というオプションを設定してみると、何ということでしょう、これまで空欄だったところに「NA」が入りました。 「一度、データファイルを保存してから、オプション設定をして読み込む」ことによって空欄にNAが入りました。 そして、そのデータファイルで作成したのが下図のグラフです。 なお、今回のレビューデータ取得の対象としたのは、2万2千件を超えるレビュー数の、自然の館の「アーモンド」です。「for i文」のステップを4にして、取得上限の1500件のうちの375件のレビューデータを取得しました。 「購入した回数」別でレビュー件数を見ると、「はじめて」という人が、意外と多いのではないかと思います。\エクストラNo.1/ アーモンド 無塩 素焼き 1kg 送料無料 素焼きアーモンド 1kg (500g×2袋) 無塩・有塩 選べるタイプになりました♪価格:1780円(税別、送料別)(2019/8/29時点)楽天で購入▼「購入した回数」別でみたレビュー件数▼性別でみたレビュー件数▼年代別に見たレビュー件数 楽天市場の商品レビューは、定型データであるため、グラフ作成のRコードを一度作成しておけば、グラフ作成をほぼ自動化できます。 さらに、「R Markdown」を使って、レポートを作成すると、使いやすく、見やすい形にまとめられるようです。 【Rコード:20190829改訂版】:「商品の使いみち」などの項目の空白のクレンジング処理を追加しています。#--------------------------------------------------url_txt <- "https://review.rakuten.co.jp/item/・・・/"pages_num <- 3get_r_reviews <- NULLdf_reviews <- NULLfor(i in seq(1, pages_num, by = 4)) { url <- paste0(url_txt,i,'.','1/') page <- read_html(url) get_r_reviews <- page %>% html_nodes ('.hreview') %>% map_df(~list( name = html_nodes(.x, '.reviewer') %>% html_text(.,trim = FALSE) %>% {if(length(.) == 0) NA else .}, title = html_nodes(.x, '.summary') %>% html_text(.,trim = FALSE) %>% {if(length(.) == 0) NA else .}, stars = html_nodes(.x, '.value') %>% html_text() %>% {if(length(.) == 0) NA else .}, date = html_nodes(.x, '.dtreviewed') %>% html_text() %>% {if(length(.) == 0) NA else .}, reviews = html_nodes(.x, '.description') %>% html_text(.,trim = FALSE) , helpful = html_nodes(.x, '.revEntryAnsNum') %>% html_text(.,trim = FALSE) %>% {if(length(.) == 0) NA else .} , age_sex = html_nodes(.x, '.revUserFaceDtlTxt') %>% html_text(.,trim = FALSE) %>% str_replace_all(., "購入者|レビュー投稿.*|.*件","") %>% str_replace_all(., " ","") %>% str_trim(., side = "both") , sex = html_nodes(.x, '.revUserFaceDtlTxt') %>% html_text(.,trim = FALSE) %>% str_replace_all(., "購入者|レビュー投稿.*|.*件|.*代|以上","") %>% str_replace_all(., " ","") %>% str_trim(., side = "both") , age = html_nodes(.x, '.revUserFaceDtlTxt') %>% html_text(.,trim = FALSE) %>% str_replace_all(., "購入者|レビュー投稿|.*件|男性|女性","") %>% str_replace_all(., " ","") %>% str_trim(., side = "both") , posts = html_nodes(.x, '.revUserFaceDtlTxt') %>% html_text(.,trim = FALSE) %>% str_replace_all(., ".*代.*|購入者|レビュー投稿|件","") %>% str_replace_all(., " ","") %>% str_trim(., side = "both") , usage1 = html_nodes(.x, '.revRvwUserDisp') %>% html_text(.,trim = FALSE) %>% str_replace_all(., "商品を使う人.*|購入した回数.*|商品の使いみち:","") %>% str_replace_all(., " ","") %>% str_trim(., side = "both") , usage2 = html_nodes(.x, '.revRvwUserDisp') %>% html_text(.,trim = FALSE) %>% str_replace_all(., "商品の使いみち.*|購入した回数.*|商品を使う人:","") %>% str_replace_all(., " ","") %>% str_trim(., side = "both") , usage3 = html_nodes(.x, '.revRvwUserDisp') %>% html_text(.,trim = FALSE) %>% str_replace_all(., "商品の使いみち.*|商品を使う人.*|購入した回数:","") %>% str_replace_all(., " ","") %>% str_trim(., side = "both") )) df_reviews <- rbind(df_reviews, get_r_reviews) print(i) Sys.sleep(5)}view(df_reviews)write.csv(df_reviews,"rakuten_reviews.csv")df_r <- read.csv("rakuten_reviews.csv",header = TRUE, na.strings=c("","NA"))write.csv(df_r ,"rakuten_reviews.csv")view(df_r)#--------------------------------------------------#レビュー件数の棒グラフ作成コード例ggplot(df_r, aes(x = sex)) + geom_bar(stat = 'count') + geom_text(aes(y = ..count.., label = ..count..),stat = 'count', vjust = 1.2, colour = "white", position = position_dodge(0.9),size = 8) + theme_bw(base_size = 14)#「☆の数」の平均値の棒グラフ作成コード例ggplot(df_r, aes(x=sex, y=stars),label=y) + stat_summary(fun.y=mean,geom="bar") + stat_summary(aes(label=round(..y..,digit=1)),fun.y=mean, geom="text", vjust = 1.5, colour = "white", position = position_dodge(0.9),size = 8) + theme_bw(base_size = 12)#-------------------------------------------------※留意事項:スクレイピングのコードの1行目と2行目については、レビューデータを取得したい商品に対応した情報を記入する必要があります。※1行目の「url_txt」の右の” ”のところに、楽天市場の特定の商品の「みんなのレビュー」の一覧ページのURLを記入するのですが、末尾の「1.1/」や「2.1/」よりも前の部分のURLの「・・・/」までを記入します。「.」や「/」が過不足しないように注意する必要があります。 「for i」文の「i」がURLの末尾の「i.1/」のところに入る形です。この「i」の後ろに「.」と「1」と「/」を付け足しています。URLの末尾が「1.1/」「2.1/」「3.1/」「4.1/」「5.1/」と変化することで、無理やり、ページ送りをしています。※2行目の「pages_num <- 3のところですが、数字の「3」のところにレビューのページの最終ページの数字を調べて記入します。10ページ目が最終ページであれば「10」を記入して「pages_num <- 10」とします。 なお、公開されているページの上限は「100」のようです。20,000件を超えるレビューがある商品でも100ページまでしか表示されません。※必要なパッケージ 私の環境ですが、Rstudioを利用しています。上記コードに必要なパッケージは、おそらく下記のようなものではないでしょうか。いろいろと試行錯誤したので、上記コードには不要なパッケージもいくつか含まれているはずです(笑)。なお、Rstudioに未登録のパッケージは、「install.packages()」などによって、インストールしておく必要があります。library(rvest)library(purrr)library(pipeR)library(textreadr)library(RCurl) library(XML)library(tidyverse)library(lubridate)library(stringr)※参考にしたページ:「Rでデータクレンジング」☆関連記事▼「R言語」による楽天市場の商品レビューのスクレイピングコードの改訂版です:Excelで項目を切り分ける作業が不要になりました▼楽天市場の特定の商品のレビューを「R言語」でスクレイピングするコード:一部の項目の空欄・欠損値(missing values)を「NA」に置き換えてデータフレームを作成:継ぎはぎのコードですが・・・▼JPRiDEの新モデル・完全ワイヤレスイヤホン「JPRiDE TWS-520」のアマゾン・カスタマーレビューのテキストを分析▼「JPRiDE」ブランドのワイヤレスイヤホン「JPRiDE 708」の楽天市場のレビューのテキストを分析:ReviewMetaでアマゾンのカスタマーレビューの信頼性の高さを推定できるJPRiDEの製品▼雑誌など第3者の高評価をアピールしている「JPRiDE(ジェイピー・ライド)」ブランドのワイヤレスイヤホン「JPA2」の楽天市場のレビューのテキスト分析です▼JVCケンウッドの高評価イヤホン「HA-FX3X」とソニーの「MDR-EX450」のカスタマーレビューを比較▼3000円クラスの高評価イヤホン「HA-FX3のカスタマーレビューのテキスト分析を「User Local」の「AIテキストマイニング」で行ってみました:こんな分析ツールがあったとは、驚きです▼カスタマーレビュー分析で、Microsoft Power BIの「Word Cloud」とスライサーの組み合わせは便利です:3000円クラスで、高評価のイヤホン「HA-FX3X」のカスタマーレビューのテキスト分析▼アマゾンのカスタマーレビューを購入の判断材料にする場合、「ReviewMeta」(レビューメータ)によるチェックが役立ちます▼先日購入したイヤホン「HA-FX3X」のアマゾン・カスタマーレビュー分析:低音の良さ、コスパなどが高評価の理由のようです:3000円クラスで、高評価のイヤホンです