教你用 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元组及文件核心对象类型详解
Feb 11 Python
Django基于ORM操作数据库的方法详解
Mar 27 Python
pandas通过字典生成dataframe的方法步骤
Jul 23 Python
python数据持久存储 pickle模块的基本使用方法解析
Aug 30 Python
wxPython窗体拆分布局基础组件
Nov 19 Python
Python一行代码解决矩阵旋转的问题
Nov 30 Python
python中count函数简单用法
Jan 05 Python
Jupyter Notebook 文件默认目录的查看以及更改步骤
Apr 14 Python
如何基于线程池提升request模块效率
Apr 18 Python
Python 分布式缓存之Reids数据类型操作详解
Jun 24 Python
基于Python实现体育彩票选号器功能代码实例
Sep 16 Python
Pytorch中的数据集划分&正则化方法
May 27 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
常用的php对象类型判断
2008/08/27 PHP
PHP中两个float(浮点数)比较实例分析
2015/09/27 PHP
php闭包中使用use声明变量的作用域实例分析
2018/08/09 PHP
一个对于js this关键字的问题
2007/01/09 Javascript
javascript 兼容鼠标滚轮事件
2009/04/07 Javascript
有效的捕获JavaScript焦点的方法小结
2009/10/08 Javascript
JS将制定内容复制到剪切板示例代码
2014/02/11 Javascript
深入浅析JavaScript中对事件的三种监听方式
2015/09/29 Javascript
HTML5 canvas 9绘制图片实例详解
2016/09/06 Javascript
微信小程序 wxapp内容组件 text详细介绍
2016/10/31 Javascript
JavaScript生成图形验证码
2020/08/24 Javascript
react-native使用react-navigation进行页面跳转导航的示例
2017/09/07 Javascript
Vue组件Draggable实现拖拽功能
2018/12/01 Javascript
监听element-ui table滚动事件的方法
2019/03/26 Javascript
小程序中canvas的drawImage方法参数使用详解
2019/07/04 Javascript
微信小程序绘制图片发送朋友圈
2019/07/25 Javascript
js回调函数仿360开机
2019/12/26 Javascript
原生js实现的观察者和订阅者模式简单示例
2020/04/18 Javascript
Vue使用预渲染代替SSR的方法
2020/07/02 Javascript
python实现的简单文本类游戏实例
2015/04/28 Python
python命令行解析之parse_known_args()函数和parse_args()使用区别介绍
2018/01/24 Python
使用python绘制二维图形示例
2019/11/22 Python
Python3实现发送邮件和发送短信验证码功能
2020/01/07 Python
如何使用Python破解ZIP或RAR压缩文件密码
2020/01/09 Python
Python实现转换图片背景颜色代码
2020/04/30 Python
宝塔面板成功部署Django项目流程(图文)
2020/06/22 Python
NARS化妆品官方商店:美国彩妆品牌
2017/08/26 全球购物
英国高级健康和美容产品零售商:Life and Looks
2019/08/01 全球购物
【魔兽争霸3重制版】原版画面与淬火MOD画面对比
2021/03/26 魔兽争霸
亲子阅读的活动方案
2014/08/15 职场文书
秋季校运会广播稿100字
2014/09/18 职场文书
2014员工聘用协议书(最新版)
2014/11/24 职场文书
工作失职自我检讨书
2015/05/05 职场文书
2016年秋季运动会通讯稿
2015/11/25 职场文书
SpringBoot集成Redis的思路详解
2021/10/16 Redis
sentinel支持的redis高可用集群配置详解
2022/04/01 Redis