问题
假设需要获取一个微信公众号h5应用的某些数据,而这个应用存在如下一些反爬措施,从而决定了获取数据的方式。
每一个操作都有类似埋点行为,这样即可收集每个用户的操作轨迹。通过轨迹正常与否,很容易判断一个用户是否在恶意获取数据。因此直接调用数据接口的方式就不可行了。
维护并验证用户token与微信accessCode的关系,这可是终极大招。微信code是无法模拟的,因此,获取数据的前提就很苛刻了,必须登录微信且从微信跳转到公众号h5应用。
针对这种情况,需要模拟人为操作如下流程,打开微信,打开公众号,打开h5应用,进行各种有目的性的点击、输入等。
目前面临的一个问题是:如何让pc知道点击哪里?
我这里选择PyAutoGUI,简介:PyAutoGUI一个用于自动化控制鼠标和键盘的跨平台Python模块。它可以模拟用户的输入行为,如点击、滚动、拖拽、键入等,非常适合用于自动化测试、任务自动化等场景。PyAutoGUI 提供了图像识别功能,可以匹配屏幕上的图片,并获取该图片在屏幕上的位置。
几个关注点
- 如何确定操作坐标:为每个操作准备一张图片,识别到图片在屏幕的坐标。
- 图片要求:图像文件应该与想在屏幕上找到的内容完全匹配。通常是截取屏幕上某个部分作为搜索目标。
- 匹配准确性:图像识别依赖于屏幕上显示内容与提供给函数的图像完全一致。任何微小差异(如颜色变化、缩放等)都可能导致无法正确匹配。
- 如何实现输入:用工具包实现复制粘贴,pyautogui只支持英文,需要用其他包如pyperclip。
- 需要为每个页面操作流程编写一遍代码
目前有两种方式,方式1是通过识别屏幕中图片,确定点击屏幕位置;方式2是时限指定固定的坐标,确定点击屏幕位置。准备6台pc,屏幕配置保持一致,包括像素和亮度。在开发机截取每一步的图片,并在开发机上测试方式1,运行的没有问题。将脚本放到其他机器,均是无法识别到图片。因此基于图片的方式就不可行了。测试方式2之前,做一些准备工作,在开发机获取某个点击点在屏幕上的坐标,保持几台电脑屏幕配置一致,包括微信图标的位置一致(例如左上角第一个图标)、窗口位置大小一致(例如全屏)、窗口位置一致(例如窗口右上角对齐屏幕右上角)。在几台电脑上测试方式2,点击和输入都符合预期。因此选择坐标方式确定操作位置。
接下来面临的一个问题:如何获取数据接口返回数据?
数据处理后最终都是结构化的。观察接口返回数据已经是结构化的,那么直接获取接口返回值并落库,后续可以解析报文并结构化存储。此时,需要考虑如何获取到http请求的报文。因此需要使用网络代理了。对网络代理要求,free,可编写脚本,可连接数据库和redis,编写脚本还得简单。我选择了mitmproxy,满足要求,不仅free而且用py写脚本。
解决
解决以上几个主要问题,基本选型已经确定,可以绘制主要模块交互图。
选型为:windows、python、PyAutoGUI、pyperclip、redis、mysql、mitmproxy。
其他需要考虑的:定时任务调度,任务驱动,pc间数据隔离。
追加
按需启动代理和配置网络代理,重新编排脚本流程:
开启代理程序-->配置系统网络代理-->执行脚本-->取消系统网络代理-->关闭代理程序。
主要点涉及子进程启动mitmproxy、程序配置网络代理、如何检查mitm启动成功。
期间遇到一个有意思的问题:
子进程启动代理并重定向日志到文件,频繁出现文件很长时间无内容,导致无法判断是否启动成功。配置了子进程和写方式打开文件的缓冲区,无效果。
解决方式:子进程执行后,提前发起网络访问,使其日志增多后自动flush。
另一个问题:windows cmd 卡住无输出
cmd 默认开启了“快速编辑模式”,因此只要鼠标点击cmd任何区域就自动进入了编辑模式,导致程序向控制台输出内容、后台的程序都会被阻塞。之后在cmd控制台回车或者右键鼠标后,自动退出编辑模式。控制台恢复输出,程序恢复正常。
解决方案:cmd 窗口菜单栏右击 -> 属性 -> 选项 -> 编辑选项处,取消“快速编辑模式”。还有一种方式是修改注册表。