今年的双十一合伙人活动需要攒猫币升级领红包,其中一种收集猫币的方式就是需要进入店铺滑动浏览。
需要工具:
一个安卓手机
思路:
之前看过github上有微信跳一跳的脚本,可以无脑刷分。使用的工具技术与其类似。核心思路如下:
1.通过adb工具模拟手指操作,获取手机屏幕截屏。
2.通过分析屏幕截屏,获取点击坐标。
具体实现过程:
1.下载adb工具,调试安卓手机
下载链接:https://developer.android.google.cn/studio/releases/platform-tools.html
下载完成后解压后如下图,并且将 C:\Users\userl\Downloads\platform-tools 加入环境变量
之后可连接安卓手机做下测试,安卓手机需要打开开发者选项USB调试,不需要越狱,开启方式可以参考如下链接:
https://jingyan.baidu.com/article/f25ef2548d7941482c1b82f4.html
好了,接下来让我们连接上手机试一下吧,在cmd 中输入adb shell中,就可以与自己的手通讯了。可以试一下一些常用的linux命令。
2.python代码
python版本3.7
需要用到的包opencv , requeset
安装命令 :
pip install opencv-python
pip install requests
主要逻辑说明:
1.在淘宝中手动进入活动主页面(如下):
2.下滑到店铺品牌列表页,需要适配下滑的距离
3.通过图像识别店铺品牌列表页面,得到需要点击的像素点位置
4.点击进入店铺,模拟滑动15后返回
5.依次重复,直到达到上限
唯一需要动脑的地方--怎么识别出品牌的坐标
我们先看下品牌列表页
思路:通过边缘检测算法,得到边缘。获得每个轮廓点集的最小包围圆。
# -*- coding: utf-8 -*-
import cv2
def cv_find_circle(filename):
img = cv2.imread(filename)
# 灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值化
ret, binary = cv2.threshold(gray, 175, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 以圆形框出
for i in range(len(contours)):
(x, y), radius = cv2.minEnclosingCircle(contours[i])
center = (int(x), int(y))
radius = int(radius)
img = cv2.circle(img, center, radius, (0, 255, 0), 2)
cv2.imwrite(filename.split(".")[0]+"_circle.png",img)
if __name__ == '__main__':
cv_find_circle("screencut0.png")
执行代码后得到如下结果,看起来效果并不是很理想,有很多干扰项。
我们采取最简单的方式来排除大部分干扰项,设定最大最小半径阈值,在1080p的手机上 ,我取了半径在40px 到400px之间,得到如下图
if radius <= 400 and radius >= 90:
candidate_circle_list.append({"center":center,"radius":radius})
img = cv2.circle(img, center, radius, (0, 255, 0), 2)
这样看起来效果好多了,不过如果直接使用的话,同一家品牌可能要点击进入多次,让费电费啊。我想了两种方法,
1.只要有两圆存在相交或包含 的情况就取其中之一即可。
2.识别详情页的文字,浏览过的店铺会提醒 任务完成-继续逛逛吧。只要判断是否存在文字,即可
试了几下后,发现方法1有缺陷,因为后面的品牌列表识别出来会呈现出如下图中,如果按照方法1筛选,就会有问题。(其实也不用考虑那么多啦,因为有每日上限,前面几家店铺逛逛就过够了)
我最后还是选用方法二的方式来实现的,因为涉及到ORC,直接用百度免费的ocr api 省力。
百度ocr-api 文档链接:https://ai.baidu.com/docs#/OCR-API/top
鉴权token获取链接:https://console.bce.baidu.com/ai/?_=1572095896806&fromai=1#/ai/ocr/app/list
根据详情页识别到的文字,来判断是否逛过,是否达到今日上线
if '今日已达上限' in res:
print("今日已达上限")
sys.exit()
if "任务完成" in res or "继续逛逛吧" in res:
print("这家店已经逛过了")
back()
else:
print("逛店中...................")
look_detail()
back()
附上效果图: