【スクレイピング】 他社の商品データを収集


概要

Pythonでのスクレイピングにより、競合など他社サイトに掲載されている商品データを収集し、

マーケティング・競合分析への活用のため、CSVファイルにまとめ、出力します

対象ページ

スクレイピング対象は、以下のようなページです

  • インテリアのECサイト
  • チェア:カテゴリの商品一覧ページ

対象データ

今回は、先述のページから

  • 商品名
  • 価格
  • レビュー|評価値
  • レビュー|投稿数

以上 4つの情報を、チェア:カテゴリの全商品分、取得します

注意

  • 記事内の「Webサイト/URL/データ」は全てダミーです
  • 記事内のコードで、実際にスクレイピングする事は可能ですが、実在のサイトに対するスクレイピングは、サーバー負担への配慮、著作権/利用規約の十分な確認等が必要となります

対象分析

対象から利用制限が指定されていないか、対象ページの構造はどうなっているか、等を分析/確認していきます

利用制限

人様のサイトからデータを取得するにあたり、まずはそのサイトの「著作権/利用規約ページ」をしっかり確認した上で、以下のコードでアクセスに対する制限を確認

. . . . .

クローリングへの指示書である「robots.txt」解析のためのモジュールurllib.robotparserをインポート

import urllib.robotparser
rp = urllib.robotparser.RobotFileParser()

robots.txtの読み込み

rp.set_url("https://demo-store.com/robots.txt")
rp.read()

request_rateで、クローラーに対し遅延時間が指定されていないかの確認

req_rate = rp.request_rate("*")
print(req_rate)
output
None

遅延時間の指定は無し。とはいえ、相手サーバー負荷への配慮として、ロード遅延処理は必須

. . . . .

can_fetchでURLの取得が許可されているかを確認

rp.can_fetch("*", "https://demo-store.com/")
output
True

Trueが返され、URL取得の許可が確認できました

ページ構造

Chrome|デベロッパーツールを用い、対象ページの構造を確認

1商品ごとにpd_boxというクラス名のパーツで囲われ、
その中に今回取得したい4つの商品情報が入っており、それぞれ以下のようにクラス名が付けられています

情報 クラス名
商品名 pd_name
価格 pd_price
レビュー:投稿数 rev_count
レビュー:評価値 rev_rate

URLの規則性

対象ページのURLは以下(※ ダミーURLです)
https://demo-store.com/living/chair/?page=1

また、この「チェア:カテゴリ|商品一覧」は、全10ページで

10ページ目のURLはhttps://demo-store.com/living/chair/?page=10となっており、
?page=XXの箇所が、現在のページ数を表しているという事が分かりました

以上を踏まえ、スクレイピング実行のコードを考えていきます

データ取得

実際にブラウザを起動・サイトを描画しながらスクレイピングする手法もありますが、今回はヘッダレスブラウザを用い、画面描写無しでサッサとスクレイピングしていきます

. . . . .

Selenium|Chromeブラウザをインポート

from selenium.webdriver import Chrome, ChromeOptions
from selenium.webdriver.common.keys import Keys

--headlessでオプション:ヘッドレスモードを有効化

options = ChromeOptions()
options.add_argument('--headless')

ChromeのWebDriverオブジェクトを作成

browser = Chrome(options=options)

後に商品情報を格納していく、空のリストを作成

names = []
prices = []
rev_rates = []
rev_counts = []

今回の対象は「商品一覧:10ページ分」つまり

https://demo-store.com/living/chair/?page=1から
https://demo-store.com/living/chair/?page=10までが対象です

よって?page={}として、ページ数箇所を変数とし、format(i)で変数箇所にiを埋め込みます

iにはfor文で1から10までの数字を順に当てはめていきます

for i in range(1,11):
    url = 'https://demo-store.com/living/chair/?page={}'.format(i)

ややこしいですがrange(1,11)で、1から10までの数字が入ることになります

. . . . .

相手サーバーへの負荷配慮としてimplicitly_waitでロードの際に3秒の間隔が空くように設定

    browser.implicitly_wait(3)

?page={}箇所に連番が入ったURL」を取得

    browser.get(url)

一覧ページでは、商品ごとにpd_boxで囲われていました
その中に、それぞれの商品名(pd_name)や価格(pd_price)が含まれている

よってpd_boxの中身を探し終えたら、次のpd_boxの中身を探し始める、という内容のfor文とします

find_elements_by_class_nameで指定したクラス名の要素を取得し、リストとしてpd_boxesに格納

    pd_boxes = browser.find_elements_by_class_name('pd_box')

pd_box1つあたりに対し、「pd_name/pd_price/rev_rate/rev_count」を探し、取得し、それぞれリストとして格納していく。完了したら次のpd_boxに対し同様の処理を行っていく

    for pd_box in pd_boxes:

        name = pd_box.find_element_by_class_name('pd_name').text
        names.append(name)

        price = pd_box.find_element_by_class_name('pd_price').text
        price = price.replace("¥","").replace(",","")
        prices.append(price)

        rev_rate = pd_box.find_element_by_class_name('rev_rate').text
        rev_rates.append(rev_rate)

        rev_count = pd_box.find_element_by_class_name('rev_count').text
        rev_count = rev_count.replace("(","").replace("件)","")
        rev_counts.append(rev_count)

名前や価格を取得しつつ、「¥」や「件」などの不要文字列はreplaceにより削除しています

. . . . .

取得したデータを確認

names
output
['Ultra Chair','Super Chair','Hyper Chair'...]
prices
output
['10000','20000','30000'...]
rev_rates
output
['5','5','5'...]
rev_counts
output
['26','36','46'...]

ちゃんとデータ取得できています

CSV出力

取得したデータは現時点では個々のリストになっているので、データフレームとしてまとめます

import pandas as pd
df = pd.DataFrame()

リスト毎に列を作成

df['name'] = names
df['price'] = prices
df['rev_rate'] = rev_rates
df['rev_count'] = rev_counts

内容確認のため、データフレームの上から5行目までを表示

df.head()
name price rev_rate rev_count
1 Ultra Chair 10000 5 26
2 Super Chair 20000 5 36
3 Hyper Chair 30000 5 46
4 Miracle Chair 40000 5 56
5 Passion Chair 50000 5 66

問題無くデータフレームになっているので、CSVファイルに変換します

df.to_csv('living_chair.csv', index=False)

CSVファイルが出力されました

総括

他社サイトの商品情報をスクレイピングで収集し、CSVファイルにまとめました

  • 各商品のレビュー投稿数を、販売数とある程度の相関があると仮定し、販売数予測の目安とする
  • 価格帯ごとのレビュー評価(満足度)を分析する

など、競合分析において活用のできる、データファイルが取得できたかと考えます