教你用 Python 实现微信跳一跳(Mac+iOS版)


Posted in Python onJanuary 04, 2018

这几天看网上好多微信跳一跳破解了,不过都是安卓的,无奈苹果不是开源也没办法。这个教程是 Mac + iOS , 要下xcode 要配置环境小白估计是没戏了,有iOS 开发经验的可以看看 。不过其实可以没事帮同事刷一下,让他们请吃个饭什么的,哈哈。 

先发个战果

教你用 Python 实现微信跳一跳(Mac+iOS版)

一.WebDriverAgent

首先去 https://github.com/facebook/WebDriverAgent 下一份代码

教你用 Python 实现微信跳一跳(Mac+iOS版) 

选择 WebDriverAgentRunner 用真机 然后 test 运行一下 , 看到IP地址就说明成功了

教你用 Python 实现微信跳一跳(Mac+iOS版) 

手机打开跳一跳 ,在电脑上访问 IP , 如我的 192.168.1.101:8100/inspector ,可以看到下面的东西

教你用 Python 实现微信跳一跳(Mac+iOS版) 

如果电脑访问 ip连接有问题 在命令行执行下面命令

$   iproxy 8100 8100

用电脑代理一下手机的8100端口

二. 去下载 wechat_jump_game

去github 下 https://github.com/wangshub/wechat_jump_game

下好之后要下载一些依赖库

$  pip install -r requirements.txt

记得 拷贝 wechat_jump_game-master ./config/iPhone 目录下对应的设备配置文件,重命名并替换到 ./config.json

教你用 Python 实现微信跳一跳(Mac+iOS版) 

将手机点击到《跳一跳》小程序界面,然后在命令行 执行 下面代码就可以自由的刷分了

$ python wechat_jump_auto_iOS.py

------------------------我是分割线------------------------------

既然身为码农就要有跟技术死磕的精神 ,比较技术就是饭碗嘛 。个人觉得python 是个神奇的东西,有着丰富的库,上可以写爬虫抓数据,下可以玩web服务。

代码核心其实就是计算出棋子和下一个砖的距离 然后 乘以 一个弹跳系数 来得到 press_time

源代码PO出来学习一下

# coding: utf-8
import os
import shutil
import time
import math
import wda
from PIL import Image, ImageDraw
import random
import json
# === 思路 ===
# 核心:每次落稳之后截图,根据截图算出棋子的坐标和下一个块顶面的中点坐标,
# 根据两个点的距离乘以一个时间系数获得长按的时间
# 识别棋子:靠棋子的颜色来识别位置,通过截图发现最下面一行大概是一条直线,就从上往下一行一行遍历,
#  比较颜色(颜色用了一个区间来比较)找到最下面的那一行的所有点,然后求个中点,
#  求好之后再让 Y 轴坐标减小棋子底盘的一半高度从而得到中心点的坐标
# 识别棋盘:靠底色和方块的色差来做,从分数之下的位置开始,一行一行扫描,由于圆形的块最顶上是一条线,
#  方形的上面大概是一个点,所以就用类似识别棋子的做法多识别了几个点求中点,
#  这时候得到了块中点的 X 轴坐标,这时候假设现在棋子在当前块的中心,
#  根据一个通过截图获取的固定的角度来推出中点的 Y 坐标
# 最后:根据两点的坐标算距离乘以系数来获取长按时间(似乎可以直接用 X 轴距离)
# TODO: 解决定位偏移的问题
# TODO: 看看两个块中心到中轴距离是否相同,如果是的话靠这个来判断一下当前超前还是落后,便于矫正
# TODO: 一些固定值根据截图的具体大小计算
# TODO: 直接用 X 轴距离简化逻辑
with open('config.json', 'r') as f:
 config = json.load(f)
# Magic Number,不设置可能无法正常执行,请根据具体截图从上到下按需设置
under_game_score_y = config['under_game_score_y'] # 截图中刚好低于分数显示区域的 Y 坐标,300 是 1920x1080 的值,2K 屏、全面屏请根据实际情况修改
press_coefficient = config['press_coefficient'] # 长按的时间系数,请自己根据实际情况调节
piece_base_height_1_2 = config['piece_base_height_1_2'] # 二分之一的棋子底座高度,可能要调节
piece_body_width = config['piece_body_width']  # 棋子的宽度,比截图中量到的稍微大一点比较安全,可能要调节
time_coefficient = config['press_coefficient']
# 模拟按压的起始点坐标,需要自动重复游戏请设置成“再来一局”的坐标
if config.get('swipe'):
 swipe = config['swipe']
else:
 swipe = {
 "x1": 320,
 "y1": 410,
 "x2": 320,
 "y2": 410
 }
c = wda.Client()
s = c.session()
screenshot_backup_dir = 'screenshot_backups/'
if not os.path.isdir(screenshot_backup_dir):
 os.mkdir(screenshot_backup_dir)
def pull_screenshot():
 c.screenshot('1.png')
def jump(distance):
 press_time = distance * time_coefficient / 1000
 print('press time: {}'.format(press_time))
 s.tap_hold(200, 200, press_time)
def backup_screenshot(ts):
 # 为了方便失败的时候 debug
 if not os.path.isdir(screenshot_backup_dir):
 os.mkdir(screenshot_backup_dir)
 shutil.copy('1.png', '{}{}.png'.format(screenshot_backup_dir, ts))
def save_debug_creenshot(ts, im, piece_x, piece_y, board_x, board_y):
 draw = ImageDraw.Draw(im)
 # 对debug图片加上详细的注释
 draw.line((piece_x, piece_y) + (board_x, board_y), fill=2, width=3)
 draw.line((piece_x, 0, piece_x, im.size[1]), fill=(255, 0, 0))
 draw.line((0, piece_y, im.size[0], piece_y), fill=(255, 0, 0))
 draw.line((board_x, 0, board_x, im.size[1]), fill=(0, 0, 255))
 draw.line((0, board_y, im.size[0], board_y), fill=(0, 0, 255))
 draw.ellipse((piece_x - 10, piece_y - 10, piece_x + 10, piece_y + 10), fill=(255, 0, 0))
 draw.ellipse((board_x - 10, board_y - 10, board_x + 10, board_y + 10), fill=(0, 0, 255))
 del draw
 im.save('{}{}_d.png'.format(screenshot_backup_dir, ts))
def set_button_position(im):
 # 将swipe设置为 `再来一局` 按钮的位置
 global swipe_x1, swipe_y1, swipe_x2, swipe_y2
 w, h = im.size
 left = w / 2
 top = 1003 * (h / 1280.0) + 10
 swipe_x1, swipe_y1, swipe_x2, swipe_y2 = left, top, left, top
def find_piece_and_board(im):
 w, h = im.size
 print("size: {}, {}".format(w, h))
 piece_x_sum = 0
 piece_x_c = 0
 piece_y_max = 0
 board_x = 0
 board_y = 0
 scan_x_border = int(w / 8) # 扫描棋子时的左右边界
 scan_start_y = 0 # 扫描的起始y坐标
 im_pixel = im.load()
 # 以50px步长,尝试探测scan_start_y
 for i in range(under_game_score_y, h, 50):
 last_pixel = im_pixel[0, i]
 for j in range(1, w):
  pixel = im_pixel[j, i]
  # 不是纯色的线,则记录scan_start_y的值,准备跳出循环
  if pixel[0] != last_pixel[0] or pixel[1] != last_pixel[1] or pixel[2] != last_pixel[2]:
  scan_start_y = i - 50
  break
 if scan_start_y:
  break
 print("scan_start_y: ", scan_start_y)
 # 从scan_start_y开始往下扫描,棋子应位于屏幕上半部分,这里暂定不超过2/3
 for i in range(scan_start_y, int(h * 2 / 3)):
 for j in range(scan_x_border, w - scan_x_border): # 横坐标方面也减少了一部分扫描开销
  pixel = im_pixel[j, i]
  # 根据棋子的最低行的颜色判断,找最后一行那些点的平均值,这个颜色这样应该 OK,暂时不提出来
  if (50 < pixel[0] < 60) and (53 < pixel[1] < 63) and (95 < pixel[2] < 110):
  piece_x_sum += j
  piece_x_c += 1
  piece_y_max = max(i, piece_y_max)
 if not all((piece_x_sum, piece_x_c)):
 return 0, 0, 0, 0
 piece_x = piece_x_sum / piece_x_c
 piece_y = piece_y_max - piece_base_height_1_2 # 上移棋子底盘高度的一半
 for i in range (int (h / 3), int (h * 2 / 3)):
 last_pixel = im_pixel[0, i]
 if board_x or board_y:
  break
 board_x_sum = 0
 board_x_c = 0
 for j in range(w):
  pixel = im_pixel[j, i]
  # 修掉脑袋比下一个小格子还高的情况的 bug
  if abs(j - piece_x) < piece_body_width:
  continue
  # 修掉圆顶的时候一条线导致的小 bug,这个颜色判断应该 OK,暂时不提出来
  if abs(pixel[0] - last_pixel[0]) + abs(pixel[1] - last_pixel[1]) + abs(pixel[2] - last_pixel[2]) > 10:
  board_x_sum += j
  board_x_c += 1
 if board_x_sum:
  board_x = board_x_sum / board_x_c
 # 按实际的角度来算,找到接近下一个 board 中心的坐标 这里的角度应该是30°,值应该是tan 30°, math.sqrt(3) / 3
 board_y = piece_y - abs(board_x - piece_x) * math.sqrt(3) / 3
 if not all((board_x, board_y)):
 return 0, 0, 0, 0
 return piece_x, piece_y, board_x, board_y
def main():
 while True:
 pull_screenshot()
 im = Image.open("./1.png")
 # 获取棋子和 board 的位置
 piece_x, piece_y, board_x, board_y = find_piece_and_board(im)
 ts = int(time.time())
 print(ts, piece_x, piece_y, board_x, board_y)
 if piece_x == 0:
  return
 set_button_position(im)
 distance = math.sqrt((board_x - piece_x) ** 2 + (board_y - piece_y) ** 2)
 jump(distance)
 save_debug_creenshot(ts, im, piece_x, piece_y, board_x, board_y)
 backup_screenshot(ts)
 time.sleep(random.uniform(1, 1.1)) # 为了保证截图的时候应落稳了,多延迟一会儿
if __name__ == '__main__':
 main()

总结

以上所述是小编给大家介绍的教你用 Python 来玩微信跳一跳(Mac+iOS版),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
python结合shell查询google关键词排名的实现代码
Feb 27 Python
详解python3实现的web端json通信协议
Dec 29 Python
python中map()函数的使用方法示例
Sep 29 Python
Python实现读取及写入csv文件的方法示例
Jan 12 Python
Python使用sax模块解析XML文件示例
Apr 04 Python
对Django中内置的User模型实例详解
Aug 16 Python
tensorflow使用指定gpu的方法
Feb 04 Python
python库skimage给灰度图像染色的方法示例
Apr 27 Python
PIL.Image.open和cv2.imread的比较与相互转换的方法
Jun 03 Python
Python使用Matlab命令过程解析
Jun 04 Python
解决Django响应JsonResponse返回json格式数据报错问题
Aug 09 Python
python 通过exifread读取照片信息
Dec 24 Python
基于python实现在excel中读取与生成随机数写入excel中
Jan 04 #Python
python实现简易云音乐播放器
Jan 04 #Python
Python语言描述连续子数组的最大和
Jan 04 #Python
一个月入门Python爬虫学习,轻松爬取大规模数据
Jan 03 #Python
Python编程pygame模块实现移动的小车示例代码
Jan 03 #Python
python编程实现随机生成多个椭圆实例代码
Jan 03 #Python
Python通过Pygame绘制移动的矩形实例代码
Jan 03 #Python
You might like
仿AS3实现PHP 事件机制实现代码
2011/01/27 PHP
基于PHP+Ajax实现表单验证的详解
2013/06/25 PHP
yii操作cookie实例简介
2014/07/09 PHP
PHP文件锁定写入实例解析
2014/07/14 PHP
PHP+MySQL修改记录的方法
2015/01/21 PHP
PHP中SESSION的注销与清除
2015/04/16 PHP
laravel框架使用FormRequest进行表单验证,验证异常返回JSON操作示例
2020/02/18 PHP
Javascript图像处理—亮度对比度应用案例
2013/01/03 Javascript
jquery统计复选框选中示例
2013/11/05 Javascript
多选列表框动态添加,移动,删除,全选等操作的简单实例
2014/01/13 Javascript
firefox下jquery ajax返回object XMLDocument处理方法
2014/01/26 Javascript
解决jquery实现的radio重新选中的问题
2015/07/03 Javascript
window.onload使用指南
2015/09/13 Javascript
angularJS与bootstrap结合实现动态加载弹出提示内容
2015/10/16 Javascript
jQuery使用contains过滤器实现精确匹配方法详解
2016/02/25 Javascript
解决koa2 ctx.render is not a function报错问题
2018/08/07 Javascript
JS+HTML5本地存储Localstorage实现注册登录及验证功能示例
2020/02/10 Javascript
vue.js实现简单的计算器功能
2020/02/22 Javascript
Vue实现简单计算器案例
2020/02/25 Javascript
简单的抓取淘宝图片的Python爬虫
2014/12/25 Python
Python开发常用的一些开源Package分享
2015/02/14 Python
使用 Python 实现简单的 switch/case 语句的方法
2018/09/17 Python
对python插入数据库和生成插入sql的示例讲解
2018/11/14 Python
python进行TCP端口扫描的实现
2018/12/21 Python
python读取word 中指定位置的表格及表格数据
2019/10/23 Python
python实现超级玛丽游戏
2020/03/18 Python
python设置表格边框的具体方法
2020/07/17 Python
新加坡鲜花速递/新加坡网上花店:Ferns N Petals
2020/08/29 全球购物
网络体系结构及协议的定义
2014/03/13 面试题
国旗下的演讲稿
2014/05/08 职场文书
2014年学校法制宣传日活动总结
2014/11/01 职场文书
幼儿园母亲节活动总结
2015/02/10 职场文书
学生不参加考试检讨书
2015/02/19 职场文书
党员转正申请报告
2015/05/15 职场文书
教师调动申请报告
2015/05/18 职场文书
详解jQuery的核心函数和事件处理
2022/02/18 jQuery