学习强国手机助手

前景:

        用手机刷学习强国时要一直盯着手机,总感觉费时费劲,刚好最近学习python写个小工具帮忙自动学习,实现了文章和视频学习,答题类不一定都能正确。上班时电脑连着USB就可以放那,自己可以上班干自己事情。

开发工具:

AirtestIDE:负责获取界面元素,poco远程解析控制手机

pycharm:负责写python逻辑,pyqt5负责界面显示日志

工具界面:

开发条件:

        Android手机,打开USB调试,第一次运行允许安装pocoservice

处理逻辑代码:

from PyQt5.QtCore import QThread, pyqtSignal
from poco.drivers.android.uiautomation import AndroidUiautomationPoco
from airtest.core.api import *
import subprocess
import redef is_in_array(array, element):for item in array:if item == element:return Truereturn False# 定义一个线程类
class QCtrlThread(QThread):# 成员read_done_tile = []  # 已读文章或视频log_signal = pyqtSignal(str)# 初始化def __init__(self, parent=None):super(QCtrlThread, self).__init__(parent)print("QCtrlThread init")# run函数是子线程中的操作,线程启动后开始执行def run(self):self.log_signal.emit("开始学习")poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False)poco.device.wake()start_app("cn.xuexi.android")sleep(2)self.get_score(poco)self.log_signal.emit("学习结束。。。")def connect_android(self):# 执行命令print("connect_android")cur_path = os.path.abspath('.')print(cur_path)run_airtest_path = cur_path + "\\airtest"cmd = r'"{}" devices'.format(run_airtest_path + '\\core\\android\\static\\adb\\windows\\adb.exe')print(cmd)if os.path.exists(run_airtest_path):p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)else:p = subprocess.Popen('adb devices', stdout=subprocess.PIPE, shell=True)# 获取输出结果output, err = p.communicate()# 处理输出结果output_str = output.decode('utf-8')print(output_str)device_list = output_str.split("\n")device_name = ""for i in range(0, len(device_list)):device_txt = device_list[i]if device_txt.find("List of devices attached") >= 0:continueprint(device_txt)if device_txt.find("device") > 0:device_split = device_txt.split("	")device_name = device_split[0]print("cmd result:", device_name)breakif len(device_name) < 8:self.log_signal.emit("设备未查找到,请连接设备,确认开发者选项-USB调试已打开")return Falsedevice_url = "Android://127.0.0.1:5037/" + device_nameself.log_signal.emit("开始连接手机设备名称:" + device_url)connect_device(device_url)return Truedef operate(self, poco):cnt_score = 0  # 得分计数list_view = poco("android.widget.FrameLayout").child("androidx.recyclerview.widget.RecyclerView").child("android.widget.FrameLayout")print("当前界面展示项:", len(list_view))for i in range(0, len(list_view)):title_view = list_view[i].offspring("cn.xuexi.android:id/general_card_title_id")if title_view.exists() is True:title_txt = title_view.get_text()self.log_signal.emit("标题:" + title_txt)if is_in_array(self.read_done_tile, title_txt) is False:  # 未读title_view.focus([0.5, 0.5]).click()sleep(1)#  开始点击音频|视频新闻self.play(poco)cnt_score += 2self.read_done_tile.append(title_txt)list_view.swipe([0, -0.5])  # 滑动return cnt_scoredef play(self, poco):self.log_signal.emit("开始视频|文章学习")#  电视if poco(name="cn.xuexi.android:id/EXTRA_INFO_LAYER_VIEW_ID"):self.log_signal.emit("开始播放视频")if poco(text="继续播放"):poco(text="继续播放").focus([0.5, 0.5]).click()while 1:if poco(text="重新播放"):breakelse:sleep(1)#  返回poco(name="cn.xuexi.android:id/EXTRA_INFO_LAYER_VIEW_ID").child("android.widget.FrameLayout")[1].child("android.widget.FrameLayout")[2].child("android.widget.ImageView").focus([0.5, 0.5]).click()else:#  文章self.log_signal.emit("开始阅读")if poco("android.widget.Button"):poco("android.widget.Button").focus([0.5, 0.5]).click()# 获取播放时间arr_view = poco("android.widget.Button").parent().child("android.view.View")#  print(len(arr_view))if len(arr_view) > 2:str_time = arr_view[2].get_text()self.log_signal.emit("时长:" + str_time)split_time = str_time.split(":")int_time = int(split_time[0]) * 60 + int(split_time[1])print("时长秒:" + str(int_time))sleep(int_time)else:# self.log_signal.emit("开始播报")# if poco(name="play-0"):#     poco(name="play-0").focus([0.5, 0.5]).clicked()# else:article_body = poco(name="xxqg-article-body")for t in range(0, 30):if article_body:article_body.swipe([0, -0.1])sleep(1)self.log_signal.emit("阅读完毕")#  返回if poco(name="cn.xuexi.android:id/TOP_LAYER_VIEW_ID"):poco(name="cn.xuexi.android:id/TOP_LAYER_VIEW_ID").child("android.widget.ImageView").focus([0.5, 0.5]).click()sleep(1)def answer(self, poco):if poco("com.uc.webview.export.WebView").exists() is False:return Falsewhile 1:if poco(name="返回"):poco(name="返回").click()break# 查看提示tips_content = ""if poco(text="查看提示"):poco(text="查看提示").focus([0.5, 0.5]).click()sleep(1)if poco(text="提示"):tips_view = poco(text="提示").parent().parent().child("android.view.View")tips_content = tips_view[1].child("android.view.View").get_text()self.log_signal.emit("提示:\n" + tips_content)tips_head = poco(text="提示").parent().child("android.view.View")tips_head[0].focus([0.5, 0.5]).click()  # 关闭提示sleep(0.5)else:article_body.swipe([0, -0.5])sleep(1)continue#  self.log_signal.emit("开始答题")if poco("android.widget.EditText"):self.log_signal.emit("填空题")if poco("android.widget.EditText"):new_content = poco("android.widget.EditText").parent().parent().child("android.view.View")edit_views = poco("android.widget.EditText").parent().child("android.view.View")  # 需要填入的项if edit_views.exists() is True:self.log_signal.emit("需要填入字数:", len(edit_views))if tips_content == "请观看视频":  # 随便选一个self.log_signal.emit("请观看视频")else:for i in range(0, len(new_content)):print(new_content[i].get_text())if len(new_content) > 1:  # 最后一段last_part_txt = new_content[len(new_content) - 1].get_text()key_txt = last_part_txt[0:4]index = tips_content.find(key_txt)if index != -1:print("填入:", tips_content[index: -1])print("填入:", tips_content[index: -2])else:self.log_signal.emit("解析错误")if poco("android.widget.ListView"):self.log_signal.emit("选择题")items = ["A.", "B.", "C.", "D.", "E."]# items_value = []is_select = Falsefor i in range(0, len(items)):  # 获取选题内容if poco(text=items[i]):item = poco(text=items[i]).parent().child("android.view.View")item_txt = item[1].get_text()self.log_signal.emit(items[i] + ":" + item_txt)if item_txt.find("正确") == 0:self.log_signal.emit("主观判断题,都判正确")poco(text=items[i]).focus([0.5, 0.5]).click()breakelse:items_value = item[1].get_text()is_sub = items_value in tips_contentif is_sub is True:self.log_signal.emit("选中:" + items[i])poco(text=items[i]).focus([0.5, 0.5]).click()is_select = Trueif poco(text="单选题"):breakelse:if tips_content == "请观看视频":  # 随便选一个poco(text=items[i]).focus([0.5, 0.5]).click()breakif poco(text="单选题") and is_select is False:poco(text=items[0]).focus([0.5, 0.5]).click()  # 默认选中第一个if poco(text="确定"):poco(text="确定").focus([0.5, 0.5]).click()sleep(1)if poco(text="下一题"):poco(text="下一题").focus([0.5, 0.5]).click()sleep(1)def get_score(self, poco):self.log_signal.emit("开始查找得分")if poco(name="cn.xuexi.android:id/comm_head_xuexi_score"):str_score = poco(name="cn.xuexi.android:id/comm_head_xuexi_score").get_text()self.log_signal.emit("得分:" + str_score)poco(name="cn.xuexi.android:id/comm_head_xuexi_score").click()sleep(2)if poco(text="学习积分"):list_class = ["我要选读文章", "我要视听学习", "每日答题"]for i in range(0, len(list_class)):print("开始学习:", list_class[i])read_news_label = poco(text=list_class[i])if read_news_label:read_news_label.swipe([0, 0.2])  # 滑动一下防止最后一项没显示sleep(1)read_news_views = read_news_label.parent().child("android.widget.TextView")print("read_news_views length:", len(read_news_views))if read_news_label.parent().child(name="去看看"):read_news_label.parent().child(name="去看看").click()  # 进入得分sleep(1)news_score_cnt = 0while 1:try:if list_class[i] == "每日答题":news_score_cnt += self.answer(poco)read_news_label.swipe([0, -0.2])  # 滑动一下防止最后一项没显示else:news_score_cnt += self.operate(poco)if news_score_cnt >= 2:breakexcept:self.log_signal.emit("解析异常")self.get_score(poco)else:self.log_signal.emit("界面不对,请回到主页面")

界面代码:

from MainWindow import *
from ctrlThread import QCtrlThread
from PyQt5.QtWidgets import QMainWindowclass XUEXIWindow(QMainWindow, Ui_MainWindow):def __init__(self, parent=None):super(XUEXIWindow, self).__init__(parent)self.setupUi(self)# 绑定按钮点击事件self.btn_start.clicked.connect(self.start)self.btn_connenct.clicked.connect(self.connect_device)self.thread = QCtrlThread()  # 实例化一个线程self.thread.log_signal.connect(self.change_log)def start(self):print('Start clicked')# 启动线程,执行线程类中run函数if self.thread.isRunning():self.textEdit.append("正在学习中...")returnself.thread.start()def connect_device(self):print("开始连接设备")self.thread.connect_android()def change_log(self, msg):print("log:", msg)self.textEdit.append(str(msg))

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

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

相关文章

内网端口转发与代理

思路&#xff1a;渗透的前提是双方能够建立通信。目前无法和win7建立通信&#xff0c;但是拿到了windows2003的权限&#xff0c;所以可以在Windows2003主机上面建立节点&#xff0c;作为跳板机去访问到内网。 目前状态&#xff1a;控制win2003&#xff08;IP&#xff1a;192.1…

扩展学习|一文读懂知识图谱

一、知识图谱的技术实现流程及相关应用 文献来源&#xff1a;曹倩,赵一鸣.知识图谱的技术实现流程及相关应用[J].情报理论与实践,2015, 38(12):127-132. &#xff08;一&#xff09;知识图谱的特征及功能 知识图谱是为了适应新的网络信息环境而产生的一种语义知识组织和服务的方…

第8篇:创建Nios II工程之读取Switch的值<一>

Q&#xff1a;本期我们再添加一个PIO组件设为输入&#xff0c;创建Nios II工程读取输入值显示在LED上。 A&#xff1a;在前2期创建的控制LED工程的Platform Designer系统基础上再添加一个PIO核&#xff0c;参数设置为18位和单向输入模式&#xff0c;表示DE2-115开发板上的18个…

Ubuntu进行换源

各种源大全 在此地 // 此源均只适用Ubuntu 18.04 版本&#xff0c;其他版本需要修改 bionic 为对应的Ubuntu版本#阿里云源地址 deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ bionic-security ma…

Anaconda删除虚拟环境目录pkgs和envs|conda瘦身

这个文件夹里面是专门放不同环境中的包的&#xff0c;只是没有区分环境&#xff0c;都混在一起了&#xff0c; 一般在想要删除一个虚拟环境&#xff0c;除了在命令行中输入conda remove -n your_env_name(虚拟环境名称) --all 然后在envs中删除虚拟环境的文件夹&#xff0c; 还…

Vector Laboratories|用于生物偶联疗法BioDesign™ dPEG® Linker连接平台

术语dPEG代表“离散PEG&#xff08;discrete PEG&#xff09;”&#xff0c;这是一种均一的、单分子量&#xff08;MW&#xff09;、高纯度的新一代聚乙二醇聚合物。Vector Laboratorie采用其受专利保护的专有生产工艺&#xff0c;可生产提供适合于各种应用场景&#xff0c;具有…

在做题中学习(50):搜索插入位置

35. 搜索插入位置 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a;二分查找 思路&#xff1a;题目是有序的&#xff0c;时间复杂度O(logN),二分没跑了&#xff0c;题目说如果找不到target&#xff0c;返回它应该被插入位置的下标&#xff0c;所以可以分析一下示例2…

ElasticSearch知识点汇总

1、ES中的​​​​​​​倒排索引是什么。 倒排索引&#xff0c;是通过分词策略&#xff0c;形成了词和文章的映射关系表&#xff0c;这种词典映射表即为倒排索引 2、ES是如何实现master选举的。 选举过程主要包括以下几个步骤&#xff1a; 心跳检测&#xff1a; 每个节点…

“Postman 中文版使用教程:如何切换到中文界面?”

Postman 的很好用的接口测试软件。但是&#xff0c;Postman 默认是英文版的&#xff0c;也不支持在软件内切换为中文版。很多同学的英语并不是很好&#xff0c;看到一堆的英文很是头痛。 今天我们来介绍下&#xff1a;切换到 Postman 中文版的方法。想要学习更多的关于 Postma…

药物代谢动力学学习笔记

一、基本概念 二、经典房室模型 三、非线性药物代谢动力学 四、非房室模型 五、药代动力学与药效动力学 六、生物等效性评价 七、生物样品分析方法 基本概念 生物样品&#xff1a;生物机体的全血、血浆、血清、粪便、尿液或其他组织的样品 特异性&#xff0c;specificity&…

nvcc: command not found

nvcc: command not found nvcc命令是 NVIDIA CUDA 编译器&#xff0c;就类似于gcc是c语言的编译器&#xff0c;用于编译 CUDA 代码并生成 GPU 可执行文件。由于程序是要经过编译器编程成可执行的二进制文件&#xff0c;而cuda程序有两种代码&#xff0c;一种是运行在CPU上的ho…

改变视觉创造力:图像合成中基于样式的生成架构的影响和创新

原文地址&#xff1a;revolutionizing-visual-creativity-the-impact-and-innovations-of-style-based-generative 2024 年 4 月 30 日 介绍 基于风格的生成架构已经开辟了一个利基市场&#xff0c;它将机器学习的技术严谨性与类人创造力的微妙表现力融为一体。这一发展的核…

消费金融平台公司如何做大做强自营产品

本文来自于2019年的某次内部分享沟通会&#xff0c;部分敏感内容已做删减。

基于python+django网易新闻+评论的舆情热点分析平台

博主介绍&#xff1a; 大家好&#xff0c;本人精通Java、Python、C#、C、C编程语言&#xff0c;同时也熟练掌握微信小程序、Php和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我有丰富的成品Java、Python、C#毕设项目经验&#xff0c;能够为学生提供各类…

密码学《图解密码技术》 记录学习 第十四章

目录 十四章 14.1 本章学习的内容 14.2 什么是 SSL/TLS 14.2.1 Alice 在 Bob 书店买书 14.2.2 客户端与服务器 14.2.3 АSSL/TLS 承载HTTP 14.2.4 SSL/TLS的工作 14.2.5 SSL/TLS也可以保护其他的协议 14.2.6 密码套件 14.2.7 SSL 与 TLS 的区别 14.3 使用 SSL/TLS 进…

如何有效访问Exness官网中文版!技巧与注意事项

Exness是一家全球知名的在线外汇和差价合约经纪商&#xff0c;为全球客户提供丰富的交易工具。由于Exness的国际化运营&#xff0c;它提供多种语言版本的官网&#xff0c;其中包括中文版。为了确保用户在Exness官网中文版的访问体验良好&#xff0c;了解一些技巧和注意事项至关…

为什么SSL证书的有效期很短?

在当今互联网世界中&#xff0c;SSL证书作为保障网站数据传输安全的重要工具&#xff0c;其有效期往往被设定为相对较短的时间。对于许多非专业人士来说&#xff0c;可能会好奇&#xff1a;为什么SSL证书不能像其他证件一样拥有较长的有效期呢&#xff1f;今天&#xff0c;我们…

桌面文件删除了怎么恢复?4个靠谱方法分享!

“我平常工作的时候喜欢将文件直接保存在电脑桌面上&#xff0c;但是今天一打开电脑&#xff0c;突然发现我的文件都不见了&#xff0c;有什么恢复桌面文件的简单方法吗&#xff1f;希望大家可以推荐几个。” 很多用户在使用电脑时可能都习惯了把文件直接放在桌面上&#xff0c…

Linux主机重启后报错:[FAILED] Failed to start Switch Root.

一、问题描述 某次云主机因计费问题&#xff0c;导致批量重启&#xff0c;重启后发现某台云主机竟进入紧急救援模式&#xff08;emergency模式&#xff09;&#xff0c;如下所示&#xff1a; 二、原因及处理 1&#xff09;原因&#xff1a;加载根分区失败&#xff0c;导致无…

盒模型,BFC以及行内块级元素

一.盒模型篇 css基础框盒模型介绍&#xff1a; 当对一个文档进行布局的时候&#xff0c;浏览器的渲染引擎会根据标准之一的css基础框盒模型&#xff0c;将所有元素表示为一个个矩形的盒子&#xff0c;每个盒子由四部分组成&#xff0c;分别是内容 内边距 边框 外边距&#xff…