Pythonスクレイピングでメルカリの商品情報を自動取得する(2022年10月版)

Pythonスクレイピングでメルカリの商品情報を自動取得する(2022年版)
スポンサーリンク
スポンサーリンク

メルカリの商品検索結果をスクレイピングして、価格情報、サムネイル画像と詳細ページへのリンクをExcelに出力する方法を解説します。

メルカリで商品を探すときに、検索結果が数ページに渡るとページ送りをするのも面倒だと思います。こちらで解説する方法でExcelに出力することで、簡単に結果を確認する事ができます。

メルカリをスクレイピングしても大丈夫?という疑問に関しては、こちらのサイトで解説されていますので参考にしてください。ここでは問題無しと判断して解説していますが、リスクは承知した上で自己責任での実施をお願いします。

また、メルカリのページ構成は頻繁に変更されますので、サンプルコードの通りに動かしても情報が取得できないこともありますので、ご了承ください。

スポンサーリンク

使用ライブラリ・ドライバ

PythonでWebスクレイピングを行うためのライブラリ Requests, Beautiful Soup,を使用します。
ライブラリの基本的な使い方は以下の記事を参照してください。
・関連記事:【入門】PythonによるWebスクレイピング

さらに、画像取得のためにPillow、Excelを扱うためのopenpyxlを使用します。
・関連記事:PythonでExcelファイルを読み書きする(openpyxl

メルカリのページをスクレイピングするためには、Selenium というライブラリを使用する必要があります。(Selenium公式ページ
この Selenium は、Webdriverを仲介してブラウザを操作するため、Webdriverのインストールも必要になります。

ここでは Chrome を利用し、Cドライブ直下にChrome用の webdriver が配置されている前提で解説します。
このドライバは、ブラウザのバージョンに合ったものを使用する必要がありますので、ブラウザのバージョンを確認して導入してください。Chromedriver入手先

ブラウザの自動更新設定が有効の場合、知らぬ間にドライバのバージョンが合わなくなりエラーが出てしまうため、注意してください。

以下のコードで必要なライブラリをまとめてインストールできます。

メルカリ商品情報(タイトル・画像・リンク)を取得してExcelに出力する

メルカリの検索結果から商品情報を取得して、タイトル・サムネイル画像・詳細ページのリンクをExcelに出力するプログラムです。

実行はコマンドプロンプトから行い、引数に検索キーワードを指定します。
※Chromedriver は、ご利用のChromeバージョンに対応したDriverを導入する必要があります。

例として上記のスクリプトのファイル名を「mercari.py」検索キーワードを「python3 入門」で実行してみます。

コマンドプロンプトに以下のように入力します。

以下がExcelに出力された結果です。
D列のURLはハイパーリンクの設定をしているので、クリックで詳細ページに飛ぶことができます。

メルカリスクレイピング取得結果

実行時に次のようなエラーが発生する場合は、Webdriverのディレクトリ指定が間違えていたり、ブラウザバージョンに対応していない為、再度確認してください。

Webdriver が導入されていない・ディレクトリ指定が間違っている。
→Webdriverを配置・配置先とスクリプト内の指定が合っているか確認。

Webdriverバージョンがブラウザバージョンに対応していない。
公式サイトから対応するバージョンをダウンロードして再配置。
 ブラウザバージョンは メニュー>ヘルプ>Google Chromeについて から確認

プログラム解説

プログラムを解説します。

プログラムは上から順に説明しますが、スクリプトを実行するとPRG1のライブラリ設定を読み込んだ後に、PRG2, 3 を含む main() 関数が実行されます。

PRG1:ライブラリ設定

プログラムを解説していきます。

import sys
import os
import time
import shutil

コマンドライン引数取得、ファイル・ディレクトリ操作、スリープを行うためのモジュールを読み込みます。

import requests
from bs4 import BeautifulSoup

HTMLのダウンロードと解析を行うためにrequests BeautifulSoupをインポートします。
インストールや基本的な使い方は以下の記事を参照してください。
・関連記事:【入門】PythonによるWebスクレイピング

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

メルカリのページをスクレイピングするためには、Seleniumが必要になるため読み込みます。インストールされていない場合は、python -m pip install selenium でインストールしてください。
・関連記事:Pythonライブラリのインストール(pipの使い方)

import io
from PIL import Image

画像処理を行うために必要なモジュール、ライブラリを読み込みます。
ここではPillowライブラリを使用しているため、インストールされていない場合は、python -m pip install Pillowでインストールを行ってください。
・公式ドキュメント:Pillow — Pillow (PIL Fork) 6.1.0 documentation

import openpyxl as px
from openpyxl.styles import Alignment

Excelに取得したデータを出力するためにopenpyxlライブラリを使用します。また、書式設定を行うためにAlignment関数を呼び出しています。

PRG2: クロール設定

クロールを行う際の初期設定を行っています。

BASE_URL = ‘https://jp.mercari.com’

クロール時のヘッダーURLを指定します。

CUR_DIR = os.getcwd()

画像ファイルを保存するディレクトリを作成するために、スクリプトが実行されているディレクトリを取得します。
getcwd()については以下の記事を参考にしてください。
・参考記事:Pythonでカレントディレクトリを取得・変更

args = sys.argv
KEYWORD = args[1]
for i in range(2,len(args)):
    KEYWORD += ‘+’ + args[i]

プログラム実行時にコマンドラインで指定した引数を読み込み、argsに格納します。
argsは、[ファイル名, 引数1, 引数2, ・・・] のように、ファイル名と引数のリストになります。
argsからファイル名を除いた引数をで結合して、検索キーワードKEYWORDに格納して、「引数1+引数2+・・・」という文字列を生成します。
・関連記事:【Python入門】argparseでコマンドライン引数を指定して実行

URL_INI = BASE_URL + ‘/search/?keyword=’ + KEYWORD + ‘&status=on_sale’
url = URL_INI

ヘッダーURLと検索キーワード、販売中のみを表示するためのURLパラメータ'&status=on_sale'を結合して、クロールするURLを生成します。

page_num = 1

検索結果ページを指定する為の変数をpage_numとして、初期値1を格納します。

# 検索結果格納リスト・画像保存フォルダ作成
result = []
if os.path.isdir(‘./img’) == False:
    os.mkdir(‘./img’)

検索した結果のアイテム情報を保存するリストresultを定義して、画像を保存するディレクトリimgを作成します。

PRG3: スクレイピング実行

スクレイピング処理をwhile trueでループさせ、breakで中断されるまで繰り返し処理を行います。


プログラムを解説します。

# ChromeでURLに接続
options = Options()
options.add_argument(‘–headless’)
browser = webdriver.Chrome(executable_path=’C:\chromedriver.exe’, options=options)
browser.get(url)
time.sleep(5)
html = browser.page_source.encode(‘utf-8’)

webdriverでクロール対象のページのHTMLを取得します。

options.add_argument('--headless') とすることでブラウザはバックグラウンドで起動され、非表示にすることができます。ブラウザを表示させたい場合はこの行をコメントアウトします。

ブラウザに結果が表示されるのを待つためにtime.sleep(5)で5秒間処理を停止させ、取得したHTMLの文字化けを避けるためpage_source.encode('utf-8')でUTF-8に変換しています。

# Beautifulsoupで要素取得
soup = BeautifulSoup(html, “html.parser”)
items_list = soup.find_all(“li”, attrs={‘data-testid’:’item-cell’})

取得したHTMLをBeautifulSoupで解析します。検索結果は、li タグの 属性名がdata-testid 値が"item-cell"であるため、find_all("li", attrs={'data-testid':'item-cell'} として、タグと属性で要素を検索して、見つかった全ての要素をitem_listとして取得します。

メルカリスクレイピング要素取得
# 商品情報取得
for i, item in enumerate(items_list):
    time.sleep(1)

取得したアイテムリストからアイテムを一つずつ取り出して、1秒間休止して必要な情報を抽出します。

# 商品名取得
item_name = item.find(“mer-item-thumbnail”).get(‘alt’)
item_name = item_name.replace(‘のサムネイル’,”)

商品名は、サムネイルの alt 属性から取得したテキストを使用しています。
属性名は、商品名 +「のサムネイル」となっているため、「のサムネイル」を replace で削除('' に置換)しています。

# サムネイル画像取得
    img_src = item.find(“mer-item-thumbnail”).get(‘src’)
    response = requests.get(img_src)
    img_fname = img_src.split(‘?’)[0].split(‘/’)[-1]
    img_bin = io.BytesIO(response.content)
    pil_img = Image.open(img_bin)
    img_resize = scale_to_width(pil_img, 200)
    img_resize.save(‘./img/’ + img_fname)

 

 

サムネイル画像のソースURLをimg_srcに格納し、requestsライブラリで画像を取得します。
取得した画像データは、io.BytesIOでバイナリデータのままPillowライブラリに渡し、後述するユーザ関数scale_to_widthで、画像の幅を指定してアスペクト比を変えずにサイズ変更を行っています。
最後に、サイズ変更した画像をimgディレクトリに保存します。

# 取得結果をリストに保存
result.append([item_name,
               int(item.find(“mer-item-thumbnail”).get(‘price’)),
               os.path.join(CUR_DIR, ‘img’, img_fname),
               BASE_URL + item.find(‘a’).get(‘href’)])

商品名、価格、画像ファイルパス、詳細ページURLをresultにリスト内リストで格納します。

# 次ページボタン処理
next_button = soup.find(‘mer-button’,attrs={‘data-testid’:”pagination-next-button”})
if next_button:
    page_num += 1
    param = ‘&page_token=v1%3A’ + str(page_num)
    next_url = URL_INI + param
    url = next_url
    next_url = ”
else:
    break

検索結果が1ページで収まる場合は次ページボタンは表示されず、複数ページになる場合は、次ページボタンが表示されます。
これを利用して、次ページ要素がある場合は、次ページのURLをクロールURLに設定してスクレイピング処理を継続し、要素が無い場合はbreakでループ処理を終了させます。

検索結果の2ページ目以降は、URLパラメータが「&page_token=v1%3A+ページ番号」で表現されているため、page_numを1ずつ増加させてヘッダURLに追加してクロールURLに設定しています。

PRG4:Excelに結果出力

取得した検索結果の情報をExcelに出力して、一覧リストとして整理します。

Excelの操作方法についてはこちらの記事を参考にしてください。
・参考記事:【Python入門】openpyxlによるExcel操作まとめ

# Excel書式設定
ws.column_dimensions[‘A’].width = 25
ws.column_dimensions[‘B’].width = 18
ws.column_dimensions[‘C’].width = 25
ws.column_dimensions[‘D’].width = 40
my_alignment=Alignment(vertical=’top’, wrap_text=True)

出力した結果を見やすくするために、列の幅を調整します。また、文字の上揃えとテキストの折返しの設定を定義します。

# 取得結果書き込み
for y, row in enumerate(result):
    ws.row_dimensions[y+2].height = 160
    for x, cell in enumerate(row):
        # 画像
        if x == 2:
            img = px.drawing.image.Image(cell)
            img.anchor = ws.cell(row= y+2, column= x+1).coordinate
            ws.add_image(img)
        # URLリンク
        elif x == 3:
            ws.cell(row= y+2, column= x+1).hyperlink = cell
            ws.cell(row= y+2, column= x+1).alignment = my_alignment
        # タイトル、価格
        else:
            ws.cell(row= y+2, column= x+1).value = cell
            ws.cell(row= y+2, column= x+1).alignment = my_alignment

resultに格納されているアイテム情報をExcelに出力していきます。

・・関連記事:PythonでExcelファイルを読み書きする(openpyxl

画像をExcelに貼り付けには、画像をopenpyxldrawing.imageモジュールを使用して読み込みます。

画像の貼り付け位置を指定するための.anchorプロパティには、A1参照形式を指定しないとエラーになるため、R1C1参照形式のcoordinate属性を取得しています。

PRG5:アスペクト比を固定して画像リサイズ

Pillowの resize メソッドでは、アスペクト比を固定できないため、画像サイズを幅に合わせて変更する関数を用意します。

width(変更後の幅) / img.width(元の幅) で、サイズ変更の比率を算出して、高さにその比率を掛けて変更後の高さを計算しています。

return でサイズ変更した画像を、戻り値として返します。

以上でプログラムの解説を終わります。

定期的に自動実行する場合は、以下の記事を参考にしてください。
・関連記事:【Win11対応】Pythonスクリプトを自動実行する方法