ADB命令来捕获设备屏幕快照和发送鼠标事件来实现抓取公众号文章

ADB命令来捕获设备屏幕和发送鼠标事件来实现抓取公众号文章
现在公众号需要登陆账号才能看到评论内容。登陆要账号的密码等,token还会过期。
现在的很多小程序进行了加密,那是否有方案可以抓取小程序或公众号的数据呢?
解决方案:
1.通过ADB命令来捕获设备屏幕快照,传递给电脑并且保存在本地文件;
2.通过百度飞桨ocr解析图片获取内容并保存;
3.根据解析的内容和坐标,向手机发送鼠标事件(点击和上下,左右滑动)来控制页面的跳转。
有待解决的问题:
百度飞桨ocr解析普通文字正确很高,但是经常把图片图标或logo识别成不同的文字,导致解析不错误。
由于公众号文章形式多样,很难统一处理,经常需要调整算法。
当然爬取普通单一样式的文章不在话下。
具体解决方案是:
开一个协程专门进行手机抓屏幕保存到电脑。
另开一个协程进行图片解析数据保存,根据解析的内容发送鼠标事件控制手机中的应用打开和翻到对应页面。
注意:
1.需要一个通过数据线连接电脑的安卓手机(苹果手机不行,不能是充电线,要是数据线,有的线只有充电功能无数据传输功能)。
2.翻页不能太快,因为ocr解析图片很慢,翻页太快会漏掉部分屏幕的解析。
3.因为公众号有记忆功能。如上次看文章翻到底部,下次再点进来看到的文章仍在底部。当下拉三次ocr识别页面相同就认为到顶,当上拉三次ocr识别的页面相同就认为到底部。
是不是很强大,把软件的加密算法变成了花瓶,达到所见即所得。这就是AI的强大应用之一,妥妥的非主流。
来分享部分抓公众号文章及评论的代码:
主程序:

async def main():print("main")sno = 0singleton1 = OCSingleton()img_path = r"screenshot.png"file_to_open = Path(img_path)if (file_to_open.is_file()):os.remove(img_path)isDawAdbScreenshot = Trueif(isDawAdbScreenshot):# 初始化Pygamepygame.init()ocr = PaddleOCR(use_angle_cls=True, lang="ch", use_gpu=False)try:await taskProccess(isDawAdbScreenshot, singleton1, ocr)except Exception as e:print('Exception:', e)await taskProccess(isDawAdbScreenshot, singleton1, ocr)finally:print('finally...')

主要的事物处理(发送鼠标事件,起协程,页面跳转控制):

async def taskProccess(isDawAdbScreenshot, singleton1, ocr):print("main 点击坐标判断0-0")# sn = 0while True:task1 = asyncio.create_task(adbPngGrap( isDawAdbScreenshot))  # 使用asyncio.create_task将函数打包成一个任务,该协程将自动排入日程等待运行task2 = asyncio.create_task(check_text_show(not isDawAdbScreenshot, ocr))if(checkNotSkip(singleton1, True)):await asyncio.sleep(4) await task1result1 = await task2# print(sno)  # 等待 task1 如果task1中存在耗时操作,则挂起print(result1)# print("main 点击坐标判断:%d ; %d" %(len(result1), (result1[0] == ['home'])))print("main 点击坐标判断0 now:%s, singleton1.sameArticleTime:%d, singleton1.isArticleTop:%d, singleton1.pageName:%s, singleton1.isNotCommonArticle:%d,singleton1.isFinishSingleArticle:%d, singleton1.backPageBox:%s, singleton1.secondBackPageBox:%s" %(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), singleton1.sameArticleTime, singleton1.isArticleTop, singleton1.pageName, singleton1.isNotCommonArticle ,singleton1.isFinishSingleArticle, singleton1.backPageBox, singleton1.secondBackPageBox))if((singleton1.pageName == '当前文章') and (not singleton1.isArticleTop) and (singleton1.down_times != 50) and (singleton1.down_times > 0)):singleton1.down_times = singleton1.down_times-1swipe_cmd = "adb shell input swipe {} {} {} {} {}".format(int(224), (int(500)), int(224),int(window_size[1]/0.3-300), int(window_size[1]/0.3-500))subprocess.run(swipe_cmd.split())print("main 点击坐标判1 向下滑动: int(start_y)= %d swipe_duration=%d, singleton1.down_times:%d" %(int(window_size[1]/0.3), int(window_size[1]/0.3-350), singleton1.down_times))await asyncio.sleep(0.1)elif((singleton1.pageName == '公众号文章列表页') and (singleton1.isBackPublicAccountsList)):backUpPage("公众号文章列表页")elif((singleton1.pageName == '当前文章') and (singleton1.isNotCommonArticle)):print("main 点击坐标判2 -0")backUpPage('当前文章')elif(isinstance(result1, list) and (5 == len(result1))):print(result1)boxUnit = result1[1]if(singleton1.isFinishSingleArticle):if  (singleton1.isNotCommonArticle) and isinstance(singleton1.articleComments, list) and isinstance(singleton1.articleCommentsBoxes, list) and (len(singleton1.articleComments) > 0) and (len(singleton1.oldArticleTitle) > 0) and (len(singleton1.articleComments) == len(singleton1.articleCommentsBoxes)):if(singleton1.oldArticleTitle != singleton1.articleTitle):if(singleton1.pageName == '当前文章'):#发送数据给后台成功print("main 点击坐标判2 -1")backUpPage("当前文章")else:if(singleton1.pageName == '当前文章'):#相同文章返回上一个页面print("main 点击坐标判2 -2")backUpPage("当前文章")else:if (not (singleton1.isNotCommonArticle)) and isinstance(singleton1.articleTitle, str) and isinstance(singleton1.articleComments, list) and isinstance(singleton1.articleCommentsBoxes, list) and (len(singleton1.articleComments) > 0):storeFile1 = OCStoreFile()print("main 自动点击对象1-0:storeFile1%d" %(id(storeFile1)))storeFile1.storeArticleData(singleton1)if(singleton1.pageName == '当前文章'):print("main 点击坐标判2 -3")backUpPage("当前文章")                    elif isinstance(boxUnit, list):if isinstance(result1[0], list) and ((result1[0] == ['article']) or (result1[0] == ['articleTop'])):if(singleton1.pageName == '当前文章'):if(result1[0] == ['article']):swipe_cmd = "adb shell input swipe {} {} {} {} {}".format(int(224), int(window_size[1]/0.3-400), int(224),(int(window_size[1]/0.3-400)-int(window_size[1]/0.3-550)), int(window_size[1]/0.3-350))print("main 点击坐标判断 向上滑动2:%d int(start_y)= %d swipe_duration=%d" %(len(result1), int(window_size[1]/0.3), int(window_size[1]/0.3-400)))else:swipe_cmd = "adb shell input swipe {} {} {} {} {}".format(int(224), (int(500)), int(224),int(window_size[1]/0.3-300), int(window_size[1]/0.3-500))print("main 点击坐标判断3 向下滑动:%d int(start_y)= %d swipe_duration=%d" %(len(result1), int(window_size[1]/0.3), int(window_size[1]/0.3-350)))subprocess.run(swipe_cmd.split())else:x = (boxUnit[0][0]+ boxUnit[1][0]+boxUnit[2][0]+boxUnit[3][0])/4.0y = (boxUnit[0][1]+ boxUnit[1][1]+boxUnit[2][1]+boxUnit[3][1])/4.0tap_cmd = adb_tap_cmd.format(int(x), int(y))# 发送tap命令到设备subprocess.run(tap_cmd.split())print("main 点击坐标判断4:%d x= %d y=%d" %(len(result1), int(x), int(y)))print("main 自动点击对象5:%s" %(result1))if(checkNotSkip(singleton1,True)):await asyncio.sleep(4) if(isDawAdbScreenshot):# 处理Pygame事件(如关闭窗口或鼠标点击)for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()elif event.type == pygame.MOUSEBUTTONDOWN:# 将鼠标点击事件转换为安卓设备的tap命令x, y = event.posx *= width / window_size[0]y *= height / window_size[1]print("main event x= %d y=%d" %(int(x), int(y)))tap_cmd = adb_tap_cmd.format(int(x), int(y))# 发送tap命令到设备subprocess.run(tap_cmd.split())elif event.type == pygame.MOUSEMOTION:# 将鼠标移动事件转换为安卓设备的坐标系x, y = event.posx *= width / window_size[0]y *= height / window_size[1]# 如果鼠标左键已按下,则将鼠标移动事件转换为滑动事件if event.buttons[0]:# 根据鼠标移动距离计算滑动距离和方向dx = event.rel[0]dy = event.rel[1]distance = (dx ** 2 + dy ** 2) ** 0.5direction = (dx / distance, dy / distance)# 计算滑动距离和速度swipe_distance = min(width, height) * distance / 200swipe_duration = int(swipe_distance)# 计算滑动的起点和终点start_x, start_y = x - direction[0] * swipe_distance / 2, y - direction[1] * swipe_distance / 2end_x, end_y = x + direction[0] * swipe_distance / 2, y + direction[1] * swipe_distance / 2# 使用ADB命令模拟滑动事件swipe_cmd = "adb shell input swipe {} {} {} {} {}".format(int(start_x), int(start_y), int(end_x),int(end_y), swipe_duration)print("main event start_x= %d start_y=%d; end_x=%d  end_y=%d; swipe_duration=%d" %(int(start_x), int(start_y), int(end_x), int(end_y), int(swipe_duration)))subprocess.run(swipe_cmd.split())# 检查Pygame事件(如关闭窗口)for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()

ADB命令来捕获设备屏幕快照并保存到电脑的代码:

async def adbPngGrap(isDraw):print("adbPngGrap 需要绘制图形:%d " %(isDraw))singleton1 = OCSingleton()if(singleton1.isConvertImage):# await asyncio.sleep(0.5)if(checkNotSkip(singleton1, True)):await asyncio.sleep(2) return# await asyncio.sleep(0.5)#抓取图片os.system("adb exec-out screencap -p > screenshot.png")# await asyncio.sleep(4)if isDraw:img_path = r"screenshot.png"file_to_open = Path(img_path)if not (file_to_open.is_file()):return Noneimage1 = cv2.imread(img_path)if image1 is None:return Noneimage = pygame.image.load('screenshot.png') # image = pygame.image.load(os.path.join('data', 'bla.png'))# 缩放图像以适应窗口大小image = pygame.transform.scale(image, window_size)# 显示图像screen.blit(image, (0, 0))pygame.display.update()print("adbPngGrap is finished!")

至于具体的业务逻辑代码(协程async def check_text_show(isDraw, ocr):)因为公司保密性和代码太长就不写了。抓小程序的内容也是同样的道理,识别出按钮的文字和坐标发送鼠标事件进行解析。有这个程序爬别人的小说何需打字员,爬虫和ocr帮你搞定一切,并且是免费的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/848647.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【简报】VITA 74 (VNX)B

1 为什么向AMSAT社区提及VPX / VNX 1.1VPX是包括卫星在内的最新一代军用车辆增长最快的标准 VITA 65 – 面向地面车辆的 OpenVPX文献检索将揭示在许多商业和军事坚固型系统应用中的广泛应用VITA 78 – AFRL和工业界正在开发用于卫星的“SpaceVPX”和“Space VPX Lite” 1.2 …

R语言数据分析15-xgboost模型预测

XGBoost模型预测的主要大致思路: 1. 数据准备 首先,需要准备数据。这包括数据的读取、预处理和分割。数据应该包括特征和目标变量。 步骤: 读取数据:从CSV文件或其他数据源读取数据。数据清理:处理缺失值、异常值等…

AWS Load Balancer Controller 实践

背景 通过编写K8S的Ingress 然后能自动创建 aws的LB 作用 控制器监视 Kubernetes Ingress 或 Service 资源。作为响应,它会创建相应的 AWS 弹性负载均衡资源。您可以通过对 Kubernetes 资源应用注释来配置负载均衡器的特定行为。例如,您可以使用注释将 AWS 安全组附加到负…

人工智能_机器学习097_PCA数据降维算法_数据去中心化_特征值_特征向量_EVD特征值分解原来和代码实现---人工智能工作笔记0222

降维算法的原理,一会咱们再看,现在先看一下,算法 可以看到PCA算法的,原理和过程,我们先看一下代码 为了说明PCA原理,这里,我们,先来计算一下X的方差,可以看到 先把数据进行去中心化,也就是用数据,减去数据的平均值. B = X-X.mean(axis=0) 这段代码是用于计算矩阵X的每一列减去该…

websockets怎么工作的呢?

WebSockets是一种在单个TCP连接上进行全双工通信的协议,使得客户端和服务器之间的数据交换变得更加简单,并允许服务端主动向客户端推送数据。下面是WebSockets的工作原理: 1. **握手阶段**: - 客户端发起一个HTTP请求到服务器&…

react+vite创建

要在本地初始化一个结合了React和Vite的项目,你可以遵循以下步骤: 1、安装Node.js: 确保你的机器上已安装了Node.js。如果未安装,请前往Node.js官网下载并安装。 2、使用终端或命令提示符: 打开你的终端(…

测试工程师经常使用的Python中的库,以及对应常用的函数

os (操作系统接口) 该库提供了许多与操作系统交互的函数,如文件处理、目录操作、进程管理等。 常用功能包括: os.name: 获取操作系统的名称。 os.path: 用于操作文件路径的模块,如os.path.join拼接路径。 os.mkdir: 创建目录。 os.remove: 删…

EE trade:通货膨胀对老百姓意味着什么

通货膨胀,是经济领域中的一个常见现象,对社会各阶层尤其是普通老百姓的生活产生了深远影响。理解通货膨胀对老百姓的真实含义,可以帮助我们更好地应对日常生活的变化与挑战。 1. 生活成本的上升 最直接的影响体现在生活成本上。通货膨胀会导致…

Linux操作系统:Redis在虚拟环境下的安装与部署

Redis下载方法 最近部署项目的时候用到了Redis,自己在安装的时候也碰到了一些列问题最终安装成功,记录一下自己的安装历程。前期准备: 服务器Linux版本:Centos8.4 64位(http://isoredirect.centos.org/centos/8/isos/…

TS设置接收的形参类型

在我们使用pinia时会接受参数&#xff0c;一般来说是传递两个参数 setGlobalState(...args: ObjToKeyValArray<GlobalState>) {this.$patch({ [args[0]]: args[1] }); } 例如此时传递的是globalStore.setGlobalState("token", "123"); 那么此时的…

python姿态识别+Tensflow1.12+pyqt5+UI

python姿态识别Tensflow1.12pyqt5UI import datetimefrom PyQt5.QtCore import QCoreApplication from PyQt5.QtWidgets import QMainWindow, QApplication, QFileDialog from vedio import vediofrom HumanPoseRec import Ui_MainWindow from PyQt5 import QtCore, QtGui, Qt…

如何使用Python提取Excel中固定单元格的内容

正文共&#xff1a;1234 字 31 图&#xff0c;预估阅读时间&#xff1a;1 分钟 之前转载了颜总的Python环境搭建文章&#xff08;Python办公自动化—环境搭建&#xff09;&#xff0c;很久过去了&#xff0c;颜总也没有再更新。现在我有一个需求&#xff0c;就是我手上有大量格…

Android Studio 下载 | 安装 | 下载 SDK | 中文插件 | 卸载

文章目录 下载安装包安装下载 SDK中文插件卸载 下载安装包 下载 Android Studio 和应用工具 - Android 开发者 | Android Developers 点击下载 Android Studio。 在协议最下方勾选同意&#xff08;第一次用最好还是看一眼&#xff09;&#xff0c;再点击 Dowload Android Stu…

JS 转化中文首字母拼音

引入 chinapy.js文件下载地址 链接&#xff1a;百度云连接 提取码&#xff1a;zrjk import { makePy } from /utils/chinapy; let chinaPyName makePy(黄飞鸿) console.log(chinaPyName) // hfh

css文字超出元素省略,单行、多行省略

通用CSS .box {width: 500px;border: 1px solid red;padding: 10px;line-height: 24px;} 1.单行省略 .singe-line {text-overflow: ellipsis;overflow: hidden;word-break: break-all;white-space: nowrap;}<p>单行省略</p><div class"singe-line box&qu…

选择核密度估计带宽LSCV与DPI方法对比

最小二乘交叉验证&#xff08;Least Squares Cross-Validation, LSCV&#xff09;和直接插入法&#xff08;Direct Plug-in, DPI&#xff09;是两种常用于选择核密度估计带宽的方法。 原理与定义 最小二乘交叉验证&#xff08;LSCV&#xff09; 原理&#xff1a;通过交叉验证…

二叉树的中序遍历-力扣

二叉树的中序遍历&#xff0c;指首先遍历左节点&#xff0c;然后遍历中间节点&#xff0c;最后遍历右节点&#xff0c;按照这个顺序进行递归即可。 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* …

【前端】JS示例:实现在一个数组(arrSstd)中查找基于uapid的值,并根据该值是否存在来决定是更新roleid还是添加新数据

要实现在一个数组&#xff08;arrSstd&#xff09;中查找基于uapid的值&#xff0c;并根据该值是否存在来决定是更新roleid还是添加新数据&#xff0c;你可以使用Array.prototype.find或Array.prototype.findIndex方法来检查是否存在具有特定uapid的对象。如果找到&#xff0c;…

GraphQL(5):使用Mutations修改数据

GraphQL中的使用Mutation查询&#xff0c;下面介绍详细操作&#xff0c;新建一个mutation.js文件。 1 定义schema 1.1 定义模型对象 &#xff08;1&#xff09;定义输入模型 input AccountInput {name: Stringage: Intsex: Stringdepartment: String} &#xff08;2&#xf…

攻防世界---misc---Ditf

1、题目描述&#xff0c;下载附件&#xff0c;是一张图片 2、打开图片&#xff0c;发现宽高不一样&#xff0c;猜测可能是需要修改宽高&#xff0c;用winhex分析&#xff0c;没有发现奇怪的地方 3、用kali中的binwalk命令&#xff0c;分析图片&#xff0c;发现有个压缩包&#…