Auto-Tinderは、TensorflowとPython3を使用してAPIをトレーニングするために作成されました。Python3は、あなたの興味を学び、Tinderスワイプゲームを自動的に再生します。

このドキュメントでは、Auto-Tinderを作成するために必要な次の手順を説明します。
Auto Tinderは、楽しみと教育の目的で純粋に作成されたコンセプトプロジェクトです。誰かを傷つけたり、プラットフォームをスパムしたりすることは決して乱用されません。 Auto-Tinderスクリプトは、Tinder Profileに確実にTindersの利用規約に違反しているため、Tinderプロファイルで使用しないでください。
このソフトウェアを主に2つの理由から書きました。
最初のステップは、TinderアプリがTinders BackEndサーバーとどのように通信するかを調べることです。 TinderはポータルのWebバージョンを提供しているため、Tinder.comに行くのと同じくらい簡単です。ChromeDevtoolsを開き、ネットワークプロトコルを簡単に確認してください。
上の写真に示されているコンテンツは、tinder.comのランディングページが読み込まれているときに作成されるhttps://api.gotinder.com/v2/recs/coreへのリクエストからのものです。明らかに、Tinderには、フロントエンドとバックエンドの間で通信するために使用している内部APIの種類があります。
/recs /coreのコンテンツを分析すると、このAPIエンドポイントが近くの人のユーザープロファイルのリストを返していることが明らかになります。
データには(他の多くのフィールドの中で)、次のデータが含まれます。
{
"meta" : {
"status" : 200
},
"data" : {
"results" : [
{
"type" : " user " ,
"user" : {
"_id" : " 4adfwe547s8df64df " ,
"bio" : " 19y. " ,
"birth_date" : " 1997-17-06T18:21:44.654Z " ,
"name" : " Anna " ,
"photos" : [
{
"id" : " 879sdfert-lskdföj-8asdf879-987sdflkj " ,
"crop_info" : {
"user" : {
"width_pct" : 1 ,
"x_offset_pct" : 0 ,
"height_pct" : 0.8 ,
"y_offset_pct" : 0.08975463
},
"algo" : {
"width_pct" : 0.45674357 ,
"x_offset_pct" : 0.984341657 ,
"height_pct" : 0.234165403 ,
"y_offset_pct" : 0.78902343
},
"processed_by_bullseye" : true ,
"user_customized" : false
},
"url" : " https://images-ssl.gotinder.com/4adfwe547s8df64df/original_879sdfert-lskdföj-8asdf879-987sdflkj.jpeg " ,
"processedFiles" : [
{
"url" : " https://images-ssl.gotinder.com/4adfwe547s8df64df/640x800_879sdfert-lskdföj-8asdf879-987sdflkj.jpg " ,
"height" : 800 ,
"width" : 640
},
{
"url" : " https://images-ssl.gotinder.com/4adfwe547s8df64df/320x400_879sdfert-lskdföj-8asdf879-987sdflkj.jpg " ,
"height" : 400 ,
"width" : 320
},
{
"url" : " https://images-ssl.gotinder.com/4adfwe547s8df64df/172x216_879sdfert-lskdföj-8asdf879-987sdflkj.jpg " ,
"height" : 216 ,
"width" : 172
},
{
"url" : " https://images-ssl.gotinder.com/4adfwe547s8df64df/84x106_879sdfert-lskdföj-8asdf879-987sdflkj.jpg " ,
"height" : 106 ,
"width" : 84
}
],
"last_update_time" : " 2019-10-03T16:18:30.532Z " ,
"fileName" : " 879sdfert-lskdföj-8asdf879-987sdflkj.webp " ,
"extension" : " jpg,webp " ,
"webp_qf" : [
75
]
}
],
"gender" : 1 ,
"jobs" : [],
"schools" : [],
"show_gender_on_profile" : false
},
"facebook" : {
"common_connections" : [],
"connection_count" : 0 ,
"common_interests" : []
},
"spotify" : {
"spotify_connected" : false
},
"distance_mi" : 1 ,
"content_hash" : " slkadjfiuwejsdfuzkejhrsdbfskdzufiuerwer " ,
"s_number" : 9876540657341 ,
"teaser" : {
"string" : " "
},
"teasers" : [],
"snap" : {
"snaps" : []
}
}
]
}
}
ここではいくつかのことが非常に興味深いものです(この人物に違反しないようにすべてのデータを変更したことに注意してください) :
コンテンツヘッダーを分析すると、プライベートAPIキーであるx-auth-tokenがすぐにわかります。
このトークンをコピーし、郵便配達員に移動することで、適切なURLと認証トークンを使用して、Tinder APIと実際に自由に通信できることを検証できます。
Tinders WebAppを少しクリックすると、関連するすべてのAPIエンドポイントをすぐに発見しました。
| タイプ | URL | 説明 |
|---|---|---|
| 得る | /v2/recs/core | 近くの人のリストを返します |
| 得る | /v2/profile?include = account%2cuser | あなた自身のプロフィールに関するすべての情報を返します |
| 得る | /V2/一致 | あなたと一致したすべての人のリストを返します |
| 得る | /like/{user_id} | 指定されたuser_idの人が好きです |
| 得る | /pass/{user_id} | 指定されたuser_idでその人に合格します |
それでは、コードに入りましょう。 Python Requests Libraryを使用して、APIと通信し、便利なためにAPIラッパークラスを周囲に書き込みます。
同様に、人を表すTinderからAPI応答を取得し、Tinder APIにいくつかの基本的なインターフェイスを提供する小さな人クラスを書きます。
Personクラスから始めましょう。 Tinder-APIオブジェクトであるAPIデータを受信し、関連するすべてのデータをインスタンス変数に保存するものとします。さらに、Tinder-APIにリクエストを行う「いいね」や「嫌い」などの基本的な機能を提供します。
import datetime
from geopy . geocoders import Nominatim
TINDER_URL = "https://api.gotinder.com"
geolocator = Nominatim ( user_agent = "auto-tinder" )
PROF_FILE = "./images/unclassified/profiles.txt"
class Person ( object ):
def __init__ ( self , data , api ):
self . _api = api
self . id = data [ "_id" ]
self . name = data . get ( "name" , "Unknown" )
self . bio = data . get ( "bio" , "" )
self . distance = data . get ( "distance_mi" , 0 ) / 1.60934
self . birth_date = datetime . datetime . strptime ( data [ "birth_date" ], '%Y-%m-%dT%H:%M:%S.%fZ' ) if data . get (
"birth_date" , False ) else None
self . gender = [ "Male" , "Female" , "Unknown" ][ data . get ( "gender" , 2 )]
self . images = list ( map ( lambda photo : photo [ "url" ], data . get ( "photos" , [])))
self . jobs = list (
map ( lambda job : { "title" : job . get ( "title" , {}). get ( "name" ), "company" : job . get ( "company" , {}). get ( "name" )}, data . get ( "jobs" , [])))
self . schools = list ( map ( lambda school : school [ "name" ], data . get ( "schools" , [])))
if data . get ( "pos" , False ):
self . location = geolocator . reverse ( f' { data [ "pos" ][ "lat" ] } , { data [ "pos" ][ "lon" ] } ' )
def __repr__ ( self ):
return f" { self . id } - { self . name } ( { self . birth_date . strftime ( '%d.%m.%Y' ) } )"
def like ( self ):
return self . _api . like ( self . id )
def dislike ( self ):
return self . _api . dislike ( self . id )私たちのAPIラッパーは、クラスを使用してTinder APIを呼び出す派手な方法以上のものではありません。
import requests
TINDER_URL = "https://api.gotinder.com"
class tinderAPI ():
def __init__ ( self , token ):
self . _token = token
def profile ( self ):
data = requests . get ( TINDER_URL + "/v2/profile?include=account%2Cuser" , headers = { "X-Auth-Token" : self . _token }). json ()
return Profile ( data [ "data" ], self )
def matches ( self , limit = 10 ):
data = requests . get ( TINDER_URL + f"/v2/matches?count= { limit } " , headers = { "X-Auth-Token" : self . _token }). json ()
return list ( map ( lambda match : Person ( match [ "person" ], self ), data [ "data" ][ "matches" ]))
def like ( self , user_id ):
data = requests . get ( TINDER_URL + f"/like/ { user_id } " , headers = { "X-Auth-Token" : self . _token }). json ()
return {
"is_match" : data [ "match" ],
"liked_remaining" : data [ "likes_remaining" ]
}
def dislike ( self , user_id ):
requests . get ( TINDER_URL + f"/pass/ { user_id } " , headers = { "X-Auth-Token" : self . _token }). json ()
return True
def nearby_persons ( self ):
data = requests . get ( TINDER_URL + "/v2/recs/core" , headers = { "X-Auth-Token" : self . _token }). json ()
return list ( map ( lambda user : Person ( user [ "user" ], self ), data [ "data" ][ "results" ]))これで、APIを使用して近くの人を見つけて、プロフィールを見ることができます。 APIトークンを以前にChrome Devコンソールで見つけたX-Auth-Tokenに交換してください。
if __name__ == "__main__" :
token = "YOUR-API-TOKEN"
api = tinderAPI ( token )
while True :
persons = api . nearby_persons ()
for person in persons :
print ( person )
# person.like() 次に、AIのトレーニングに使用できる近くの人の画像を自動的にダウンロードしたいと思います。 「Some」では、1500〜2500の画像のようなものを意味します。
まず、画像をダウンロードできる関数を使用して、人クラスを拡張しましょう。
# At the top of auto_tinder.py
PROF_FILE = "./images/unclassified/profiles.txt"
# inside the Person-class
def download_images ( self , folder = "." , sleep_max_for = 0 ):
with open ( PROF_FILE , "r" ) as f :
lines = f . readlines ()
if self . id in lines :
return
with open ( PROF_FILE , "a" ) as f :
f . write ( self . id + " r n " )
index = - 1
for image_url in self . images :
index += 1
req = requests . get ( image_url , stream = True )
if req . status_code == 200 :
with open ( f" { folder } / { self . id } _ { self . name } _ { index } .jpeg" , "wb" ) as f :
f . write ( req . content )
sleep ( random () * sleep_max_for )Tinder CDNをスパムして数秒で多くの写真をダウンロードするとブロックされる可能性があるからといって、あちこちでランダムスリープを追加したことに注意してください。
すべての人々のプロフィールIDを「profiles.txt」というファイルに書き込みます。特定の人がすでにそこにいるかどうかを最初にドキュメントをスキャンすることで、すでに出会った人をスキップすることができ、数回人を分類しないようにします(これがリスクである理由が後でわかります)。
近くの人をループして、「分類されていない」フォルダーに画像をダウンロードできるようになりました。
if __name__ == "__main__" :
token = "YOUR-API-TOKEN"
api = tinderAPI ( token )
while True :
persons = api . nearby_persons ()
for person in persons :
person . download_images ( folder = "./images/unclassified" , sleep_max_for = random () * 3 )
sleep ( random () * 10 )
sleep ( random () * 10 )これで、このスクリプトを開始し、数時間実行して、近くの人のいくつかのハンドレットプロファイル画像を取得することができます。 Tinder Proユーザーの場合は、今すぐあなたの場所を更新してから、新しい人を獲得してください。
操作する画像がたくさんあるので、本当にシンプルで醜い分類器を作りましょう。
「分類されていない」フォルダーのすべての画像をループし、GUIウィンドウで画像を開くだけです。人を右クリックすることで、人を「嫌い」とマークすることができ、左クリックはその人を「いいね」とマークします。これは、Filenameで後述します: 4TZ3KJLDFJ3482.jpgは、画像を「いいね」または0_4TZ3KJLDFJ3482.jpgとしてマークする場合、 1_4TZ3KJLDFJ3482.jpgに名前が変更されます。 Like/Disliseは、Filenmaeの初めに1/0としてエンコードされます。
TKINTERを使用して、このGUIをすばやく書き込みましょう。
from os import listdir , rename
from os . path import isfile , join
import tkinter as tk
from PIL import ImageTk , Image
IMAGE_FOLDER = "./images/unclassified"
images = [ f for f in listdir ( IMAGE_FOLDER ) if isfile ( join ( IMAGE_FOLDER , f ))]
unclassified_images = filter ( lambda image : not ( image . startswith ( "0_" ) or image . startswith ( "1_" )), images )
current = None
def next_img ():
global current , unclassified_images
try :
current = next ( unclassified_images )
except StopIteration :
root . quit ()
print ( current )
pil_img = Image . open ( IMAGE_FOLDER + "/" + current )
width , height = pil_img . size
max_height = 1000
if height > max_height :
resize_factor = max_height / height
pil_img = pil_img . resize (( int ( width * resize_factor ), int ( height * resize_factor )), resample = Image . LANCZOS )
img_tk = ImageTk . PhotoImage ( pil_img )
img_label . img = img_tk
img_label . config ( image = img_label . img )
def positive ( arg ):
global current
rename ( IMAGE_FOLDER + "/" + current , IMAGE_FOLDER + "/1_" + current )
next_img ()
def negative ( arg ):
global current
rename ( IMAGE_FOLDER + "/" + current , IMAGE_FOLDER + "/0_" + current )
next_img ()
if __name__ == "__main__" :
root = tk . Tk ()
img_label = tk . Label ( root )
img_label . pack ()
img_label . bind ( "<Button-1>" , positive )
img_label . bind ( "<Button-3>" , negative )
btn = tk . Button ( root , text = 'Next image' , command = next_img )
next_img () # load first image
root . mainloop ()分類されていないすべての画像を「unclassified_images」リストにロードし、tkinterウィンドウを開き、next_img()を呼び出して最初の画像をパックし、画像をサイズにして画面に合わせます。次に、2回のクリック、右クリック、右マウスボタンを登録し、ラベルに従って画像を変更して次の画像を表示する陽性/負の関数を呼び出します。
醜いが効果的。
次のステップでは、画像データを分類を実行できる形式にする必要があります。データセットを考えると、考慮する必要があるいくつかの困難があります。
私たちはこれらの課題と戦う:

最初の部分は、枕を使用して画像を開き、グレースケールに変換するのと同じくらい簡単です。 2番目の部分では、「人」のラベルも含まれているCoCoデータセットで事前に処理されたMobileNetネットワークアーキテクチャでTensorflowオブジェクト検出APIを使用します。
人を検出するためのスクリプトには4つの部分があります。
私のgithubリポジトリには、tensorflow mobilenet cocoグラフの.bpファイルがあります。 Tensorflowグラフとして開いてみましょう:
import tensorflow as tf
def open_graph ():
detection_graph = tf . Graph ()
with detection_graph . as_default ():
od_graph_def = tf . GraphDef ()
with tf . gfile . GFile ( 'ssd_mobilenet_v1_coco_2017_11_17/frozen_inference_graph.pb' , 'rb' ) as fid :
serialized_graph = fid . read ()
od_graph_def . ParseFromString ( serialized_graph )
tf . import_graph_def ( od_graph_def , name = '' )
return detection_graph画像操作には枕を使用します。 Tensorflowはデータを使用するために生のnumpyアレイが必要なので、枕の画像をnumpy配列に変換する小さな関数を書きましょう。
import numpy as np
def load_image_into_numpy_array ( image ):
( im_width , im_height ) = image . size
return np . array ( image . getdata ()). reshape (
( im_height , im_width , 3 )). astype ( np . uint8 )次の関数は画像とTensorflowグラフを採用し、Tensorflowセッションを使用して実行し、検出されたクラス(オブジェクトタイプ)、境界ボックス、スコアに関するすべての情報を返します(オブジェクトが正しく検出されたことは確実です)。
import numpy as np
from object_detection . utils import ops as utils_ops
import tensorflow as tf
def run_inference_for_single_image ( image , sess ):
ops = tf . get_default_graph (). get_operations ()
all_tensor_names = { output . name for op in ops for output in op . outputs }
tensor_dict = {}
for key in [
'num_detections' , 'detection_boxes' , 'detection_scores' ,
'detection_classes' , 'detection_masks'
]:
tensor_name = key + ':0'
if tensor_name in all_tensor_names :
tensor_dict [ key ] = tf . get_default_graph (). get_tensor_by_name (
tensor_name )
if 'detection_masks' in tensor_dict :
# The following processing is only for single image
detection_boxes = tf . squeeze ( tensor_dict [ 'detection_boxes' ], [ 0 ])
detection_masks = tf . squeeze ( tensor_dict [ 'detection_masks' ], [ 0 ])
# Reframe is required to translate mask from box coordinates to image coordinates and fit the image size.
real_num_detection = tf . cast ( tensor_dict [ 'num_detections' ][ 0 ], tf . int32 )
detection_boxes = tf . slice ( detection_boxes , [ 0 , 0 ], [ real_num_detection , - 1 ])
detection_masks = tf . slice ( detection_masks , [ 0 , 0 , 0 ], [ real_num_detection , - 1 , - 1 ])
detection_masks_reframed = utils_ops . reframe_box_masks_to_image_masks (
detection_masks , detection_boxes , image . shape [ 1 ], image . shape [ 2 ])
detection_masks_reframed = tf . cast (
tf . greater ( detection_masks_reframed , 0.5 ), tf . uint8 )
# Follow the convention by adding back the batch dimension
tensor_dict [ 'detection_masks' ] = tf . expand_dims (
detection_masks_reframed , 0 )
image_tensor = tf . get_default_graph (). get_tensor_by_name ( 'image_tensor:0' )
# Run inference
output_dict = sess . run ( tensor_dict ,
feed_dict = { image_tensor : image })
# all outputs are float32 numpy arrays, so convert types as appropriate
output_dict [ 'num_detections' ] = int ( output_dict [ 'num_detections' ][ 0 ])
output_dict [ 'detection_classes' ] = output_dict [
'detection_classes' ][ 0 ]. astype ( np . int64 )
output_dict [ 'detection_boxes' ] = output_dict [ 'detection_boxes' ][ 0 ]
output_dict [ 'detection_scores' ] = output_dict [ 'detection_scores' ][ 0 ]
if 'detection_masks' in output_dict :
output_dict [ 'detection_masks' ] = output_dict [ 'detection_masks' ][ 0 ]
return output_dict最後のステップは、画像パスを取得し、枕を使用して開き、オブジェクト検出APIインターフェイスを呼び出し、検出された人の境界ボックスに従って画像をトリミングする関数を書き込むことです。
import numpy as np
from PIL import Image
PERSON_CLASS = 1
SCORE_THRESHOLD = 0.5
def get_person ( image_path , sess ):
img = Image . open ( image_path )
image_np = load_image_into_numpy_array ( img )
image_np_expanded = np . expand_dims ( image_np , axis = 0 )
output_dict = run_inference_for_single_image ( image_np_expanded , sess )
persons_coordinates = []
for i in range ( len ( output_dict [ "detection_boxes" ])):
score = output_dict [ "detection_scores" ][ i ]
classtype = output_dict [ "detection_classes" ][ i ]
if score > SCORE_THRESHOLD and classtype == PERSON_CLASS :
persons_coordinates . append ( output_dict [ "detection_boxes" ][ i ])
w , h = img . size
for person_coordinate in persons_coordinates :
cropped_img = img . crop ((
int ( w * person_coordinate [ 1 ]),
int ( h * person_coordinate [ 0 ]),
int ( w * person_coordinate [ 3 ]),
int ( h * person_coordinate [ 2 ]),
))
return cropped_img
return None最後のステップとして、「分類されていない」フォルダーのすべての画像をループするスクリプトを書きます。名前にエンコードされたラベルがあるかどうかを確認します。
import os
import person_detector
import tensorflow as tf
IMAGE_FOLDER = "./images/unclassified"
POS_FOLDER = "./images/classified/positive"
NEG_FOLDER = "./images/classified/negative"
if __name__ == "__main__" :
detection_graph = person_detector . open_graph ()
images = [ f for f in os . listdir ( IMAGE_FOLDER ) if os . path . isfile ( os . path . join ( IMAGE_FOLDER , f ))]
positive_images = filter ( lambda image : ( image . startswith ( "1_" )), images )
negative_images = filter ( lambda image : ( image . startswith ( "0_" )), images )
with detection_graph . as_default ():
with tf . Session () as sess :
for pos in positive_images :
old_filename = IMAGE_FOLDER + "/" + pos
new_filename = POS_FOLDER + "/" + pos [: - 5 ] + ".jpg"
if not os . path . isfile ( new_filename ):
img = person_detector . get_person ( old_filename , sess )
if not img :
continue
img = img . convert ( 'L' )
img . save ( new_filename , "jpeg" )
for neg in negative_images :
old_filename = IMAGE_FOLDER + "/" + neg
new_filename = NEG_FOLDER + "/" + neg [: - 5 ] + ".jpg"
if not os . path . isfile ( new_filename ):
img = person_detector . get_person ( old_filename , sess )
if not img :
continue
img = img . convert ( 'L' )
img . save ( new_filename , "jpeg" )このスクリプトを実行すると、すべてのラベル付き画像が処理され、「クラシファイド」ディレクトリの対応するサブフォルダーに移動されます。
再訓練部分には、InceptionV3モデルを使用してTensorflows Retrain.pyスクリプトを使用するだけです。
次のパラメーターを使用して、プロジェクトルートディレクトリのスクリプトを呼び出します。
python retrain.py --bottleneck_dir=tf/training_data/bottlenecks --model_dir=tf/training_data/inception --summaries_dir=tf/training_data/summaries/basic --output_graph=tf/training_output/retrained_graph.pb --output_labels=tf/training_output/retrained_labels.txt --image_dir=./images/classified --how_many_training_steps=50000 --testing_percentage=20 --learning_rate=0.001GTX 1080 TIで学習には約15分かかり、ラベル付きデータセットの最終的な精度は約80%ですが、これは入力データの品質とラベル付けに大きく依存します。
トレーニングプロセスの結果は、「TF/Training_output/retrained_graph.pb」ファイルの再訓練InceptionV3モデルです。 Tensorflowグラフの新しい重みを効率的に使用して分類予測を作成する分類子クラスを作成する必要があります。
グラフをセッションとして開く分類子クラスを書き、ラベルが「ポジティブ」と「ネガティブ」に一致する確実性値を持つDICTを返す画像ファイルを使用して「分類」メソッドを提供します。
クラスは、グラフへのパスとラベルファイルへのパスの両方を入力して、どちらも「TF/Training_output/」フォルダーに座っています。画像ファイルをテンソルに変換するためのヘルパー関数を開発し、グラフにフィードできる、グラフとラベルをロードするためのヘルパー関数、および使用が完了した後にグラフを閉じる重要な小さな関数を開発します。
import numpy as np
import tensorflow as tf
class Classifier ():
def __init__ ( self , graph , labels ):
self . _graph = self . load_graph ( graph )
self . _labels = self . load_labels ( labels )
self . _input_operation = self . _graph . get_operation_by_name ( "import/Placeholder" )
self . _output_operation = self . _graph . get_operation_by_name ( "import/final_result" )
self . _session = tf . Session ( graph = self . _graph )
def classify ( self , file_name ):
t = self . read_tensor_from_image_file ( file_name )
# Open up a new tensorflow session and run it on the input
results = self . _session . run ( self . _output_operation . outputs [ 0 ], { self . _input_operation . outputs [ 0 ]: t })
results = np . squeeze ( results )
# Sort the output predictions by prediction accuracy
top_k = results . argsort ()[ - 5 :][:: - 1 ]
result = {}
for i in top_k :
result [ self . _labels [ i ]] = results [ i ]
# Return sorted result tuples
return result
def close ( self ):
self . _session . close ()
@ staticmethod
def load_graph ( model_file ):
graph = tf . Graph ()
graph_def = tf . GraphDef ()
with open ( model_file , "rb" ) as f :
graph_def . ParseFromString ( f . read ())
with graph . as_default ():
tf . import_graph_def ( graph_def )
return graph
@ staticmethod
def load_labels ( label_file ):
label = []
proto_as_ascii_lines = tf . gfile . GFile ( label_file ). readlines ()
for l in proto_as_ascii_lines :
label . append ( l . rstrip ())
return label
@ staticmethod
def read_tensor_from_image_file ( file_name ,
input_height = 299 ,
input_width = 299 ,
input_mean = 0 ,
input_std = 255 ):
input_name = "file_reader"
file_reader = tf . read_file ( file_name , input_name )
image_reader = tf . image . decode_jpeg (
file_reader , channels = 3 , name = "jpeg_reader" )
float_caster = tf . cast ( image_reader , tf . float32 )
dims_expander = tf . expand_dims ( float_caster , 0 )
resized = tf . image . resize_bilinear ( dims_expander , [ input_height , input_width ])
normalized = tf . divide ( tf . subtract ( resized , [ input_mean ]), [ input_std ])
sess = tf . Session ()
result = sess . run ( normalized )
return result 分類器が配置されたので、「人」クラスを以前から拡張し、分類器インスタンスを使用して特定の人を好むべきかどうかを確認する「Predict_likeliness」関数で拡張しましょう。
# In the Person class
def predict_likeliness ( self , classifier , sess ):
ratings = []
for image in self . images :
req = requests . get ( image , stream = True )
tmp_filename = f"./images/tmp/run.jpg"
if req . status_code == 200 :
with open ( tmp_filename , "wb" ) as f :
f . write ( req . content )
img = person_detector . get_person ( tmp_filename , sess )
if img :
img = img . convert ( 'L' )
img . save ( tmp_filename , "jpeg" )
certainty = classifier . classify ( tmp_filename )
pos = certainty [ "positive" ]
ratings . append ( pos )
ratings . sort ( reverse = True )
ratings = ratings [: 5 ]
if len ( ratings ) == 0 :
return 0.001
return ratings [ 0 ] * 0.6 + sum ( ratings [ 1 :]) / len ( ratings [ 1 :]) * 0.4これで、すべてのパズルピースをまとめる必要があります。
まず、APIトークンでTinder APIを初期化しましょう。次に、再訓練グラフとラベルを使用して、Tensorflowセッションとして分類Tensorflowグラフを開きます。次に、近くに人をフェットし、可能性のある予測を行います。
少しボーナスとして、Tinderの人が私と同じ大学に行った場合、私は1.2の可能性のマルチプライヤーを追加しました。
0.8の予測される潜在スコアを持っているすべての人について、私は同様に、他のすべての人が嫌いと呼びます。
スクリプトが開始されてから2時間後に自動プレイするスクリプトを開発しました。
from likeliness_classifier import Classifier
import person_detector
import tensorflow as tf
from time import time
if __name__ == "__main__" :
token = "YOUR-API-TOKEN"
api = tinderAPI ( token )
detection_graph = person_detector . open_graph ()
with detection_graph . as_default ():
with tf . Session () as sess :
classifier = Classifier ( graph = "./tf/training_output/retrained_graph.pb" ,
labels = "./tf/training_output/retrained_labels.txt" )
end_time = time () + 60 * 60 * 2
while time () < end_time :
try :
persons = api . nearby_persons ()
pos_schools = [ "Universität Zürich" , "University of Zurich" , "UZH" ]
for person in persons :
score = person . predict_likeliness ( classifier , sess )
for school in pos_schools :
if school in person . schools :
print ()
score *= 1.2
print ( "-------------------------" )
print ( "ID: " , person . id )
print ( "Name: " , person . name )
print ( "Schools: " , person . schools )
print ( "Images: " , person . images )
print ( score )
if score > 0.8 :
res = person . like ()
print ( "LIKE" )
else :
res = person . dislike ()
print ( "DISLIKE" )
except Exception :
pass
classifier . close ()それでおしまい!親指を乱用せずに、私たちが好きな限りスクリプトを実行し、Tinderを演奏できるようになりました!
質問がある場合やバグが見つかった場合は、GitHubリポジトリに自由に貢献してください。
MITライセンス
Copyright(c)2018 Joel Barmettler
このソフトウェアおよび関連するドキュメントファイル(「ソフトウェア」)のコピーを取得している人に、これにより許可が無料で許可され、制限なしにソフトウェアを扱うことができます。 、ソフトウェアのコピーを公開、配布、サブライセンス、および/または販売し、次の条件を条件として、ソフトウェアが提供される人を許可します。
上記の著作権通知とこの許可通知は、ソフトウェアのすべてのコピーまたはかなりの部分に含まれるものとします。
このソフトウェアは、商品性、特定の目的への適合性、および非侵害の保証を含むがこれらに限定されない、明示的または黙示的なものを保証することなく、「現状のまま」提供されます。いかなる場合でも、著者または著作権所有者は、契約、不法行為、またはその他の訴訟、ソフトウェアまたは使用またはその他の取引に関連する、またはその他の契約、またはその他の請求、またはその他の責任について責任を負いません。ソフトウェア。
私たちを雇う:チューリッヒのソフトウェア・エントウィックラー!