创建了自动诱因是为了使用TensorFlow和Python3训练API,该API了解您的兴趣并自动为您播放Tinder Swiping游戏。

在本文档中,我将解释创建自动诱因所需的以下步骤:
Auto Tinder是一个纯粹是出于娱乐和教育目的而创建的概念项目。它绝不会滥用伤害任何人或垃圾邮件。自动诱因脚本不应与您的Tinder配置文件一起使用,因为它们肯定违反了Tinders的服务条款。
我已经写了这件软件,主要是有两个原因:
第一步是找出Tinder应用如何通信到Tinders后端服务器。由于Tinder提供了其门户网站的网络版本,因此这与访问tinder.com,打开Chrome DevTools并快速查看网络协议一样容易。
上图中显示的内容是从https://api.gotinder.com/v2/recs/core的请求,该内容是在tinder.com登录页面加载时制作的。显然,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 。
通过复制这个令牌并转向Postman,我们可以验证我们确实可以使用正确的URL和我们的auth令牌自由地与Tinder API自由通信。
通过单击Tinders WebApp,我很快发现了所有相关的API端点:
| 类型 | URL | 描述 |
|---|---|---|
| 得到 | /v2/rec/core | 返回附近的人名单 |
| 得到 | /v2/profile?include = account%2cuser | 返回有关您自己个人资料的所有信息 |
| 得到 | /v2/匹配 | 返回所有与您匹配的人的清单 |
| 得到 | /light/{user_id} | 喜欢给定的用户_id的人 |
| 得到 | /通过/{user_id} | 通过给定的User_id通过 |
因此,让我们进入代码。为了方便起见,我们将使用Python请求库与API进行通信,并围绕它编写API包装类。
同样,我们写了一个小人班,该课程从代表一个人的Tinder中获得API响应,并为Tinder API提供了一些基本接口。
让我们从班级开始。它应接收API数据,Tinder-API对象,并将所有相关数据保存为实例变量。它将进一步提供一些基本功能,例如“喜欢”或“不喜欢”,向Tinder-API提出请求,这使我们可以方便地使用“ some_person.like()”,以便喜欢我们发现有趣的个人资料。
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在附近找到人们,并查看他们的个人资料,甚至像所有人一样。用您早些时候在Chrome Dev Console中发现的X-Auth-Toke替换您的API 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。有了“一些”,我的意思是像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 )请注意,我在这里和那里添加了一些随机的睡眠,仅仅是因为如果我们垃圾邮件垃圾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窗口中打开图像。通过右键单击一个人,我们可以将该人标记为“不喜欢”,而左键单击将其标记为“喜欢”。稍后将在文件名中表示: 4TZ3KJLDFJ3482.JPG如果我们将图像标记为“喜欢”或0_4TZ3KJJLDFJ3482.JPG ,则将重命名为1_4TZ3KJLDFJ3482.JPG 。标签类似/不喜欢的标签在FileMae开头编码为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 ()我们将所有未分类的图像加载到“ Unclansified_images”列表中,打开一个TKINTER窗口,通过调用Next_img()将第一个图像打包到其中,然后调整图像大小以适合屏幕。然后,我们注册两次点击,左右鼠标按钮,并将函数调用为正/负数,以根据其标签重命名图像并显示下一个图像。
丑陋但有效。
在下一步中,我们需要将图像数据带入允许我们进行分类的格式。考虑到我们的数据集,我们必须考虑一些困难。
我们通过以下方式应对这些挑战:

第一部分就像使用枕头打开我们的图像并将其转换为灰度一样容易。在第二部分中,我们将TensorFlow对象检测API与Mobilenet网络体系结构一起使用,该架构在可可数据集上预处理,该数据集也包含“人”标签。
我们的人检测脚本有四个部分:
您在我的GitHub存储库中找到了Tensorflow Mobilenet可可图的.bp文件。让我们以张量图图表打开它:
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" )当我们运行此脚本时,所有标记的图像都将被处理并移至“分类”目录中的相应子文件夹中。
对于重新培训部分,我们将仅将TensorFlows Retrain.py脚本与InceptionV3模型一起使用。
使用以下参数调用项目根目录中的脚本:
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.001在GTX 1080 Ti上,学习大约需要15分钟,最终的精度约为我的标签数据集,但这在很大程度上取决于输入数据的质量和标签。
培训过程的结果是“ TF/Training_Output/retrained_graph.pb”文件中的Retrest 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 现在,我们已经拥有分类器,让我们从较早的时候扩展“人”类,并使用“ precept_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。然后,我们使用REAR的图形和标签打开分类张量图作为张量式会话。然后,我们在附近取出人,做出可能的预测。
一点点的奖励,如果Tinder上的人与我一样,我添加了1.2的可能性,以便我更有可能与当地学生匹配。
对于所有预测的可能得分为0.8的人来说,我称之为其他人都不喜欢。
我将脚本开发为在启动后的接下来的两个小时内自动播放。
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存储库做出贡献。
麻省理工学院许可证
版权(C)2018 Joel Barmettler
特此免费授予任何获得此软件副本和相关文档文件(“软件”)的人,以无限制处理该软件,包括无限制,使用,复制,修改,合并的权利,发布,分发,分布和/或出售该软件的副本,并允许提供该软件的人,但要遵守以下条件:
上述版权通知和此许可通知应包含在软件的所有副本或大量部分中。
该软件是“原样”提供的,没有任何形式的明示或暗示保证,包括但不限于适销性,特定目的的适用性和非侵权的保证。在任何情况下,作者或版权持有人均不应对任何索赔,损害赔偿或其他责任责任,无论是在合同,侵权或其他方面的诉讼中,与软件或与软件或使用或其他交易有关的诉讼或其他责任软件。
雇用我们:苏软件在苏黎世!