メルカリをスクレイピングしていきます。
最初は、カテゴリー一覧ページからスクレイピングします。
なぜ、カテゴリー一覧ページからスクレイピングすると思いますか?
その回答は、後ほど説明します。
本記事の内容
- スクレイピングの種類
- 大量データのスクレイピング方法
- カテゴリー一覧ページのスクレイピング
- メルカリの珍しいスクレイピング対策
それでは、上記に沿って解説していきます。
スクレイピングの種類
スクレイピングには、大きく分けて二つの種類があります。
- 大量データの抜き出し
- 指定ページの監視
大量データとは、その言葉通りに多くのデータのことです。
場合によっては、全データということもあるでしょう。
また、指定した分類のみのデータということもあります。
分類の例としては、以下のようなモノがあります。
- カテゴリー
- 年
- キーワード
上記の大量データの抜き出しは、イメージしやすいでしょうね。
もう一つの指定ページの監視は、あまり認知されていないかもしれません。
例えば、ある商品の在庫をチェックするなどで使う手段です。
実際、私はSwitchが手に入りにくいときにその手をつかいました。
販売ページにおいて在庫があるなら、「〇」が表示される仕様だったはずです。
「〇」を認識したら、自動でLineに通知するようにしていました。
当時は、その仕組みによりSwitchを手に入れることができました。
スクレイピングには、そのような使い方もあるという良い例ですね。
今回は、大量データの抜き出しのパターンとなります。
このパターンを説明していきます。
大量データのスクレイピング方法
大量データを取得するためには、各データ(メルカリなら商品)のURLを知る必要があります。
正直、このデータのURLリストを用意することがスクレイピングの肝となります。
ここは、設計能力が問われる部分と言っても過言ではありません。
つまり、対象サイトのデータの持ち方(データ構造)を理解する必要があるのです。
このことをターゲットとなるメルカリで確認していきましょう。
まず、スクレイピングする際、カテゴリー一覧からデータを抽出していきます。
カテゴリー一覧をスクレイピングすれば、カテゴリーIDを取得できます。
メルカリにもカテゴリー一覧ページが存在します。
https://www.mercari.com/jp/category/
現時点では、以下が大カテゴリーとして扱われています。
大カテゴリーの数は、全部で13個ですね。

大カテゴリーの下には、多くのカテゴリーが紐づいています。
しかし、大カテゴリーのIDを取得できれば、それでOKです。
次に、カテゴリーIDからそのカテゴリーに紐づく商品一覧ページのURLを作成できます。
そして、商品一覧ページをスクレイピングすれば、商品IDを取得できます。
さらに、商品IDからその商品詳細ページのURLが作成可能です。
このようにドリルダウンしていくことで、最小単位となる商品までたどり着けます。
結果として、商品ページのURLリストを作成できます。
このURLリストがあれば、あとはそれをバッチ処理で対応していくだけです。
では、メルカリのカテゴリーページをスクレイピングしてみましょう。
カテゴリー一覧ページのスクレイピング
これから実際に動くプログラムを載せていきます。
各自でそのプログラムを動かす場合は、次の記事で準備をしてください。
そして、絶対に【必須】は読んでください。
そうしないと、大変なことになりかねません。
準備が整ったら、次のコードを動かしていきましょう。
サンプルコードとして、現時点(2021年2月4日)で動くコードを載せています。
サンプルコード
import bs4
import traceback
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
# ドライバーのフルパス
CHROMEDRIVER = "chromedriver.exeのパス"
# ドライバー準備
def get_driver():
# ヘッドレスモードでブラウザを起動
options = Options()
options.add_argument('--headless')
# ブラウザーを起動
driver = webdriver.Chrome(CHROMEDRIVER, options=options)
return driver
# 対象ページのソース取得
def get_source_from_page(driver, page):
try:
# ターゲット
driver.get(page)
driver.implicitly_wait(10) # 見つからないときは、10秒まで待つ
page_source = driver.page_source
return page_source
except Exception as e:
print("Exception\n" + traceback.format_exc())
return None
# ソースからスクレイピングする
def get_data_from_source(src):
# スクレイピングする
soup = bs4.BeautifulSoup(src, features='lxml')
#print(soup)
try:
info = []
# 大カテゴリー毎に要素を取得
elems = soup.find_all(attrs={"data-test": "category-list-individual-box"})
for elem in elems:
# 最初に出てくるaタグ(「すべて」)の要素を取得
a_tag = elem.find("a")
if a_tag:
href = a_tag.attrs['href']
category_id = href.replace("/jp/category/", "")
info.append(category_id)
return info
except Exception as e:
print("Exception\n" + traceback.format_exc())
return None
if __name__ == "__main__":
# 対象ページURL
page = "https://www.mercari.com/jp/category/"
# ブラウザのdriver取得
driver = get_driver()
# ページのソース取得
source = get_source_from_page(driver, page)
# ソースからデータ抽出
data = get_data_from_source(source)
# 閉じる
driver.quit()
# 結果表示
print(data)
上記を実行すると、次の結果が表示されます。
大カテゴリーのIDです。
['1', '2', '3', '4', '5', '1328', '6', '7', '8', '9', '1027', '1318', '10']
全部で13個あるので、上手くスクレイピングできています。
正直、13個程度ならスクレイピングまでする必要はありませんけどね。
プログラムの内容は、細かくは説明しません。
「大量データのスクレイピング方法」をベースにプログラミングしています。
それに、コメントを見れば大体は理解できるはずです。
以下だけ説明しておきましょう。
# ドライバーのフルパス CHROMEDRIVER = "chromedriver.exeのパス"
これは、それぞれの環境で異なるでしょう。
各自で値を変更してください。
以上で終わってもいいのですが、最後にメルカリのスクレイピング対策について説明しておきます。
メルカリの珍しいスクレイピング対策
「カテゴリー一覧ページのスクレイピング」では、サクッとスクレイピングしています。
しかし、少しだけ苦労しました。
それは、メルカリのサイトがスクレイピング対策をしているからです。
それも地味に嫌な対策をしてきます。
私は、過去に多くのサイトをスクレイピングしてきました。
しかし、メルカリの対策は初めてのケースかもしれません。
その対策とは、タグ要素のclass名をセッション毎に変更するのです。
例えば、カテゴリー一覧には次ようなタグが存在しています。
「name=”category-1″」で検索すれば、ヒットします。
<div name="category-1" data-test="category-list-individual-box" class="sc-kvkilB ducAME">
ただし、「class=”sc-kvkilB ducAME”」部分は異なる値のはずです。
このようなclass名の値が、セッション毎に異なってきます。
だから、class名を使って要素を抽出できないのです。
スクレイピングをやる上で、これは地味にダメージを受けます。
しかし、データ属性に関してはセッション毎に変更することはありません。
上記の例でいえば、「data-test=”category-list-individual-box”」の部分です。
そのため、メルカリではclass名ではなくデータ属性でスクレイピングをしていきます。
次回は、商品一覧画面のスクレイピングを行う予定です。
その際にも、この考え方で対応できるのかどうかということですね。
やっぱり、スクレイピングは面白いです。
各サイトのエンジニアとの知恵比べが、単純にワクワクします。


