Love-ITブログ
オレジとほりぽたのIT&介護を中心とした日常系ブログ
IT

GASを使ってメルカリの取引完了メールから商品情報をスプレッドシートに取り込む方法

black and gray laptop computer

フリマアプリのメルカリはとても便利ですが、出品者サイドから見ると販売データのCSVダウンロードができないなど不便な点も多いです。

事業としてメルカリを利用している方は、販売データをリスト化しないと売上管理や会計などのシステムに登録ができません。

本記事では、GASを使ってメルカリの販売データをスプレッドシートに登録する方法を紹介します。

メルカリには販売データのCSVダウンロード機能がない

メルカリはブラウザ版もアプリ版も販売履歴は表示されますが、データをダウンロードする機能はついておらず、リスト化するには何らかの方法を考える必要があります。

メルカリの販売データをリスト化する方法
  • 売上実績ページを表示してコピー&ペーストで貼り付ける
  • 販売実績ページのデータをWebスクレイピングを使って取得する
  • メルカリから取引完了時に送られてくるメールを解析してリスト化する

売上実績ページを表示してコピー&ペーストで貼り付ける

最も簡単な方法ですが、数が多くなると時間がかかったりミスも発生しやすくなったり、結果的に高コストになるため、おすすめはしません。

販売実績ページのデータをWebスクレイピングを使って取得する

Webスクレイピングとは、指定したWebページから必要な情報を取得するプログラムのことをいい、様々な分野で利用されています。

しかしWebスクレイピングは、運用方法を間違えるとサイトを攻撃していることになるため、訴訟問題になることもあるそうです。

また、苦労してプログラムを作成しても、取得するサイトのレイアウトが変更されたり、セキュリティ上で対策をされると使えなくなるというリスクもあります。

メルカリから取引完了時に送られてくるメールを解析してリスト化する

メルカリは取引が完了すると商品情報が記載されたメールが送られますので、GASを使って販売リストを作成します。

取引完了メールには販売金額の記載はありますが送料や手数料の記載はありません。
ゆうゆうメルカリ便しか使わないなど送料が固定の場合は手数料の計算ができますが、送料が変わるときは、手動かWebスクレイピングを利用してデータを取得する必要があります。

手順

それではGASで作っていきましょう!

GASを利用するにはGoolgeアカウントが必要です。Googleアカウントがない人はまずは作りましょう。

Gmailでラベルの設定

取引完了メールにラベルをつけて、他のメールと混ざらないようにします。
ラベル名は「メルカリ取引完了」などわかりやすいものにして、リスト化する取引完了メールにラベルつけましょう。

[Gmailヘルプ]ラベルを作成してGmailを整理する
https://support.google.com/mail/answer/118708?hl=ja&ref_topic=3394656

また、今後、取引完了メールを受信したときに自動的にラベルが付くようにメールフィルタを作成しましょう。

[Gmail]メールのフィルタルールの作成
https://support.google.com/mail/answer/6579?hl=ja&ref_topic=3394656

スプレッドシートを作成しスクリプトエディタを起動

GoogleDriveに移動して必要な場所にスプレッドシートを作成するか、スプレッドシートの管理画面から作成しましょう。

スプレッドシートが表示されたら、メニューバーからツールスクリプトエディタの順にクリックをして、スクリプトエディタを起動しましょう。

GooleDriveやスプレッドシートに移動するときは、Gmailの右上にあるGoogleアプリボタン(テンキーみたいなボタン)から移動すると簡単です。

GASはスクリプト単体で実行するものと、スプレッドシートなどのサービスと紐づいて実行するものがあります。必ずスプレッドシートを経由するわけではありません。

スクリプト(プログラム)を書きます

前提として、ラベル名をメルカリ取引完了、シート名をdataと想定して作っていますので、それぞれの環境に変更して使ってください。

ソースコード

//初期設定 ここから
  //Gmailの件名を設定
  const SUBJECT ="【メルカリ】取引が完了しました";

  //Gmailのラベル名を設定
  const LABEL ="メルカリ取引完了";
  
  //スプレッドシートのシート名
  const SHEET_NAME ="data"

//初期設定ここまで

function myFunction() {

  //検索条件の設定
  let query ="";
  query += "LABEL:" + LABEL + " SUBJECT:" + SUBJECT;

  //Gmailから検索条件に合うメールを取り出す
  const myThreads = GmailApp.search(query);
  const myMsgs = GmailApp.getMessagesForThreads(myThreads);

  /*
  Gmailではスレッド(Thred)とメール(Mail)という2次元配列の概念があります
  スレッドとメールの関係は1対多となります
  */
  for (let threadIndex = 0 ; threadIndex < myThreads.length ; threadIndex++ ) {
    for (let mailIndex =0 ; mailIndex< myMsgs[threadIndex].length; mailIndex++){

      // 本文の文字列を取得します
      const mailBody = myMsgs[threadIndex][mailIndex].getPlainBody();

      /*
      正規表現により、メール本文から必要な情報を取得します。
      */

      //商品ID
      let itemID = mailBody.match(/商品ID : (.+)/);

      //商品名
      let itemName = mailBody.match(/商品名 : (.+)/);

      //商品価格 カンマ(,)と円の文字は消します
      let itemPrice = mailBody.match(/商品価格 : (.+)/);
      itemPrice[1]= itemPrice[1].replace(",","");
      itemPrice[1]= itemPrice[1].replace("円","");

      //メール受信日
      let mailDate = myMsgs[threadIndex][mailIndex].getDate();

      //データを書き込むシートを選択
      const objSheet = SpreadsheetApp.getActive().getSheetByName(SHEET_NAME);

      //一番上のレコードに行を挿入してデータを書き込む
      objSheet.insertRowAfter(1);

      //正規表現で取得したデータをセルに書き込む
      objSheet.getRange("A2").setValue(itemID[1]);
      objSheet.getRange("B2").setValue(itemName[1]);
      objSheet.getRange("C2").setValue(itemPrice[1]);

      //メール受信日をセルに書き込む
      objSheet.getRange("D2").setValue(mailDate);
    }
  }
}

本プログラムは自由に使っていただいて結構ですが実行結果の責任は負いかねますので、ご自身の責任においてご利用ください。

解説

初期設定

ラベル名やシート名など使う人の環境によって変わるものは、ソースコードの開始時に書くと見落としが少なくなります。また、ソースコード内ではなく、シートや外部ファイルに設定を書きだすとさらに利便性が上がります。

スレッドとメールの関係

Gmailではメールはスレッドと呼ばれるグループにまとめらており、スレッドからメールデータを取り出すときはmyMsgs[threadIndex][mailIndex].getPlainBody();というように二次元配列になります(myMsgsはスレッドを格納している変数です)

正規表現について

正規表現は指定した文字列から、検索条件に合う結果を配列に返してくれます。

正規表現についての難しい話は抜きにして、例えば商品ID : m123456789という文字列から、m123456789 を取り出したい場合は、itemID = "商品ID:m123456789".match(/商品ID : (.+)/);とすると、配列itemID[0]商品ID : m123456789ItemID[1]m123456789が返ってきますので、商品IDを使いたいときはItemID[1]を使えばよいということになります。

上記のmatchメソッドでどうしてm123456789が配列に入るの?と疑問を持つ人もいると思います。これは()はキャプチャグループといい、()内の検索結果も配列に返ってくるという仕様のためです。

スプレッドシートにレコードを挿入する方法について

行を追加するときは、レコードの一番下に追加するというイメージがあるかもしれませんが、その場合は行数の取得などの処理が入ることと、予期しないデータが入っているとレコードの連続性が損なわれる恐れがあります。

ですので、レコードを挿入するときはレコードの一番上に行を挿入してそこにデータを書き込むことをおすすめします。この方法だとレコード数を数える必要がないので他のプログラムにも流用できます。

登録時のレコード順番はあまり気にしないようにしましょう。リストでは並び替えを多用しますので、日付や商品IDなど基準となるフィールドをレコードに入れておきましょう。

このプログラムの既知の問題点と改善点

実行結果はうまくいったでしょうか?プログラミングの経験がない方は中々難しかったと思います。

実は、このプログラムは若干の問題点がありますが、今回はGASを使ってメールをスプレッドシートに取り込むところを中心に解説をしました。

今後、需要があればこれらの問題点を改善していく記事を書こうと思います。

プログラムの問題点
  • 実行すると毎回全データを取りに行く
  • 手数料や送料が取得できない
  • メールの数が多くなると処理ができなくなる

実行すると毎回全データを取りに行く

この問題を解決するには2つの方法があります。

  • 一度取り込んだデータを次回移行取り込まない
  • 期間を指定して取り込む

一度取り込んだデータを次回移行取り込まない

これを実現するには、Gmailで設定する方法と、プログラム側で設定する方法があり、いざいうときに備えてどちらも設定するのがおすすめです。

Gmailで設定する方法

取り込んだメールにスターをつけることで取り込み済みかどうかの判別ができます。

GAS上ではスターはメール単位に設定ができるのでスターがついていれば取込済、ついていなければ未取込として処理ができます。

なお、ラベルはスレッドごとに設定されるので、取込済のラベルに変更することで管理をすることはできません。

プログラム側で設定する方法

もう一つの方法は、スクリプト側でレコードに書き込むときに商品IDを検索することで、取込済か未取込かを判断します。

期間を指定して取り込む

Gmailで期間指定で検索することにより取込済のメールを取り込まなくする方法です。

この方法では、年月日を指定した検索できますが時間を指定した検索ができないので、当日のデータを取り込むと重複する恐れがあります。
ただ、この方法と別の方法(スターをつけるなど)を組み合わせることで当日のデータ取り込みにも対応できそうです。

手数料や送料が取得できない

メルカリから届く取引完了メールには手数料や送料がないため、メールからの取得はできません。

ただ、取引完了メールで商品IDがわかるので、Webスクレイピングを使ってメルカリの取引完了画面にアクセスをして、手数料や送料の情報が取得できそうです。

Webスクレイピングのほかに、PowerAutoDesktopなどのRPAツールを使っても実現できそうです。

メールの数が多くなると処理ができなくなる

GASの仕様上、検索結果の取得上限やプログラムの実行時間などに制限があり、大量に処理を行う場合は複数回に分ける必要があります。

GASの制限について
Quotas for Google Services
https://developers.google.com/apps-script/guides/services/quotas?hl=ja

また、GASにはトリガーという定期的にスクリプトを自動実行する機能があり、次回以降データを取り込まない仕組みが作成できれば自動取込ができそうです。

まとめ

GASを利用して、メールの内容を解析してスプレッドシートに転記するプログラムを作成しましたがいかがでしたでしょうか?

完全自動に向けてはまだまだ課題があるので、今後の改善テーマにしようと思います。

また、今後もGASをはじめExcelVBAなど社内SEとして知っておいたほうがよいTipsなども紹介できたらいいなと思います。