Help us understand the problem. What is going on with this article?

Pythonでつくる彼女入門 ~Tinder自動化プロジェクト~ 第2話

More than 1 year has passed since last update.

更新情報

2019/6/17 typo修正

目次

やったこと 主な出来事
第1話 自動右スワイプ
第2話 自動メッセージ送信 女性とマッチした
第3話 ライブラリ化 マッチした女性とLINEを交換した
第3.5話 アクセストークンの再取得 これまでのコードではトークンが取得できなくなっていた
第4話 データ収集 LINEの返信が来なくなった
第5話 データ分析 プロフィール文編 仲良くなった人から情報商材を勧められた
第6話 データ分析 画像編 リアルの知り合い女子から最近やたらと深夜に電話がかかってくる(?)

コードはGitHubから閲覧できます。

前回までのあらすじ

  • Tinderのアカウントを作成した
  • 端末からTinderにログインした
  • 自動右スワイプを実装した

前回の結果とその反省

前回記事から約2週間、思い出すたびに自動右スワイプを実行したところ、無事に何人かの方とマッチすることに成功しました!!
スクリーンショット 2019-05-15 1.19.57.png

念願の彼女に向け、一歩前進です。一方、プログラムにいくつか改良の余地も見えてきました。今回は前回プログラムの修正と拡張から始めていきたいと思います。

メッセージを送るのが面倒くさい

互いに右スワイプを送り合い、マッチした相手とはメッセージをやり取りすることができます。ここでマッチした相手を口説き、デートに誘い出すというのがTinderの基本的な使い方だそうですが、このメッセージを送るという作業が面倒くさくなりました。会話となればいざしらず、メッセージの第一声など「はじめまして」以外にないでしょう。同じメッセージを何度もコピペで送るくらいなら、その作業は自動化してしまいましょう。

マッチ情報の取得

まずは、マッチした相手を取得します。
/updatesに、last_activity_dateというパラメーターを添えてPOSTでアクセスすると、マッチ(とその他よくわからない?情報)が返ってきます。last_activity_dateには何を入力すればいいのかイマイチわからなかったのですが(恐らく何かしらの日付?)、とりあえず0を渡したら動きました。必要な情報だけを抜き出していきます。

tinder.py
from accessToken import getAccessToken
import requests
import json

FBemail = "Facebookのメールアドレス"
FBpass = "Facebookのパスワード"

# FBトークンの取得
token = getAccessToken(FBemail, FBpass)

# Tinderのトークンの取得
with requests.Session() as s:
    params = {"token": token}
    response = s.post(
        "https://api.gotinder.com/v2/auth/login/facebook?local=ja", data=json.dumps(params))
    response = json.loads(response.text)
    api_token = response["data"]["api_token"]

    # Tinderのヘッダーをセット
    headers = {"X-Auth-Token": api_token, "Content-type": "application/json",
               "User-agent": "Tinder/10.1.0 (iPhone; iOS 12.1; Scale/2.00)"}
    s.headers.update(headers)

    # マッチを取得
    matches = s.post("https://api.gotinder.com/updates",
                     data=json.dumps({"last_activity_date": 0}))
    matches = json.loads(matches.text)["matches"]
    for match in matches:
        try:
            match_id = match["id"]
            user_id = match["person"]["_id"]
            name = match["person"]["name"]
            print("{0}:\tuser_id={1}\tmatch_id={2}".format(
                name, user_id, match_id))
        except:
            pass

メッセージ送信

上記で取得したmatch_idを用いて、/user/matches/{match_id}にPOSTでアクセスするとメッセージを送信することができます。パラメーターは{"message": message}です。ということで、

tinder.py
#前略
    for match in matches:
        try:
            match_id = match["id"]
            name = match["person"]["name"]
            s.post("https://api.gotinder.com/user/matches/{0}".format(
                match_id), data=json.dumps({"はじめまして!\nマッチありがとうございます!"}))
        except:
            pass

として実行することで、マッチした人全員にメッセージを送ることができます

新しいマッチにだけメッセージを送信

上記のコードをそのまま実行すると、すでに会話している人にも「はじめまして」のメッセージが送られます。それでは流石に使いづらいので、マッチをしたはいいけれど未だなんのメッセージも送信していない人にだけメッセージを送ります。先程取得した返り値には、送受信したメッセージも含まれているので、コードは以下のとおりです。

tinder.py
#前略
    for match in matches:
        try:
            match_id = match["id"]
            name = match["person"]["name"]
            messages = match["messages"]
            if len(messages) == 0:
                s.post("https://api.gotinder.com/user/matches/{0}".format(
                    match_id), data=json.dumps({"はじめまして{0}さん!\nマッチありがとうございます!".format(name)}))
        except:
            pass

これで、新しいマッチに自動でメッセージを送ることが出来るようになりました。

半日に1度起動するのが面倒くさい

Tinderは、追加で課金をしない限り、右スワイプ出来る回数が12時間あたり100回までと決められています。ここ数日、半日に一度ほど自動右スワイププログラムを起動していましたが、面倒くさいです。アプリを開いて右スワイプするよりは楽だと言うものの、面倒くさいものは面倒くさいのです。なので、コードを半日に一度自動で起動することにします。

AWS Lambdaを利用する

AWS Lambda はサーバーをプロビジョニングしたり管理する必要なくコードを実行できるコンピューティングサービスです。[1]
AWS Lambdaを用いることで、プログラムを定期的に実行することができます(他にも様々な使い方がありますが、ここでは触れません)。プログラムの実行時間に応じて料金がかかりますが、1,000,000件/月のリクエストまでは無料で実行することができるので、Tinderを自動化する分には料金はかかりません12

下準備

AWS Lambdaにアップロードするコードを準備します。
AWS Lambdaでは、lambda_function.pyに記載されたlambda_handler(event, context)という関数を実行することができるので、これまでのtinder.pyを少し修正します。引数のevent, contextはLambdaから渡されるものですが、今回は特に使いません。
位置情報登録、自動右スワイプ、自動メッセージ送信を実装したいので、メインのコードは次の通り。

lambda_function.py
from accessToken import getAccessToken
import requests
import json

FBemail = "Facebookのメールアドレス"
FBpass = "Facebookのパスワード"


def lambda_handler(event, context):
    # FBトークンの取得
    token = getAccessToken(FBemail, FBpass)

    # Tinderのトークンの取得
    with requests.Session() as s:
        params = {"token": token}
        response = s.post(
            "https://api.gotinder.com/v2/auth/login/facebook?local=ja", data=json.dumps(params))
        response = json.loads(response.text)
        api_token = response["data"]["api_token"]

        # Tinderのヘッダーをセット
        headers = {"X-Auth-Token": api_token, "Content-type": "application/json",
                   "User-agent": "Tinder/10.1.0 (iPhone; iOS 12.1; Scale/2.00)"}
        s.headers.update(headers)

        # 位置情報の登録
        location = {"lat": 35.658034, "lon": 139.701636}  # 渋谷スクランブル交差点
        ping = s.post("https://api.gotinder.com/v2/meta",
                      params=json.dumps(params))

        likes_remaining = True
        while likes_remaining:
            # 周囲のユーザーを取得
            users = s.post("https://api.gotinder.com/user/recs")
            for user in json.loads(users.text)["results"]:
                id = user["_id"]
                # 右スワイプ
                like = s.get("https://api.gotinder.com/like/{}".format(id))
                like = json.loads(like.text)
                # スワイプの残りがなくなったら終了
                if like["likes_remaining"] == 0:
                    likes_remaining = False

        # マッチを取得
        matches = s.post("https://api.gotinder.com/updates",
                         data=json.dumps({"last_activity_date": 0}))
        matches = json.loads(matches.text)["matches"]
        for match in matches:
            try:
                match_id = match["id"]
                name = match["person"]["name"]
                messages = match["messages"]
                if len(messages) == 0:
                    s.post("https://api.gotinder.com/user/matches/{0}".format(
                        match_id), data=json.dumps({"はじめまして{0}さん!\nマッチありがとうございます!".format(name)}))
            except:
                pass

これに加え、AWS Lambda上ではpipが使えないので、事前に手元にライブラリを準備する必要があります。
pip install requests robobrowser -t .として、手元にrequestsとrobobrowserのソースコードを用意してください。
最後に、requests,robobrowserのコード一式と、lambda_function.py, accessToken.pyをまとめてzipに圧縮すれば、下準備は完了です。

関数の登録

AWSのアカウントを所持していない人は、まずアカウントを作成する必要があります。本記事では詳しく解説はしないので、参考文献[2]等を見てください。

AWSのコンソールにサインインしたあと、サービス一覧からlambdaを選択します。
右上の「関数の作成」クリックし、好きな関数名を入力(今回はTinderとします)。ランタイムはPython3.6を選択します。
そして、適切なアクセスロールを選択します。よくわからなければ「基本的な Lambda アクセス権限で新しいロールを作成」を選択すればOKです。
Lambda関数が作成されたら、中段の「関数コード」内にある「コード エントリ タイプ」で「.zipファイルをアップロード」を選択し、先程圧縮したコードをアップロードします。
これでLambda関数の登録は完了です。
右上の保存ボタンを押した後、テストボタンを押してください。lamda_handler(event,context)が実行されるはずです。テストイベントの設定を要求されるかも知れませんが、適当なイベント名を入力して作成を押せばOKです(今回は使わないので)。400エラーが発生した際は、Facebookに不審なアクセスとしてブロックされていないか確認してください。

定期実行

無事にコードが起動できたら、定期実行の設定を行います。
「Designer」から「ColudWatch Events」を選択し、「新規ルールの作成」を選びます。
適当なルール名とルールの説明を入力したあと、「ルールタイプ」を「スケジュール式」にセットし、スケジュール式にrate(12 hours)と入力します。
追加ボタンを押せば、設定完了です。




これにて、12時間毎に自動で右スワイプを実行し、新しくマッチした人に自動でメッセージを送れるようになりました。
そろそろコードが汚くなってきたので、次回はコードを整理し、ライブラリ化したいと思います。次回までには、1人くらいデートできるといいなぁ。
それでは次回をお楽しみに。

第3話はこちら

参考文献

[1]https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/welcome.html
[2]https://aws.amazon.com/jp/register-flow/
[3]https://qiita.com/speedkingg/items/b285a2149a461f7fb489


  1. 執筆当時の情報です。最新の料金体系は、公式サイトでご確認ください。 

  2. 無料枠には実行回数以外にも一定の条件があるようです。本記事の内容を実行する分には無料枠を超過することは無いはずですが、念の為ご自身でもご確認ください。 

Fulltea
( ; ; ) ← 無限ループに泣かされている人の顔文字です。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away