【2020/2/22第一次优化】
【初始代码见Python-Appium自动化测试-学习通自动刷视频(1)(有讲解)】
【仅供学习交流使用】
【本文是对(1)的补充】
有需求就有动力…
【2020/2/22】更新内容:
在CxAuto类中增添功能函数
def num_of_xpath(self, x_path):
if not self.is_element_xpath_exist(x_path):
return 0
return len(cx_driver.find_elements_by_xpath(x_path))
设置course_index默认值为-1,默认进入代号选课模式,也可通过(1)中最初始的输入课程下标启动刷视频代码
def __init__(self):
self.course_index = -1
self.screenWidth = cx_driver.get_window_size()["width"]
self.screenHeight = cx_driver.get_window_size()["height"]
def start_point_course(self):
if self.course_index == -1:
self.course_index = self.start_choose_course()
# 点击具体课程
course_xpath = "//android.widget.RelativeLayout/android.support.v7.widget.RecyclerView/android.widget.FrameLayout[%s]" % self.course_index
if self.wait_element_by_xpath(course_xpath, 5):
WebDriverWait(cx_driver, 10).until(EC.element_to_be_clickable((By.XPATH, course_xpath)),
message='timeout').click()
print("打开课程,开始了哦")
def start_choose_course(self):
while True:
course_xpath = "//android.widget.RelativeLayout/android.support.v7.widget.RecyclerView/android.widget.FrameLayout"
self.wait_element_by_xpath(course_xpath, 5)
courses = cx_driver.find_elements_by_xpath(course_xpath)
codes = []
# 依次将代号和课程名称打印出来
for course in courses:
course_name = course.find_element_by_id("com.chaoxing.mobile:id/tv_name").get_attribute("text")
course_code = int(courses.index(course)) + 1
codes.append(course_code)
print(course_code, " -- ", course_name)
is_eligible = input("这些课程有合您心意吗?[True/False]")[0].upper()
if is_eligible == "T":
while True:
course_index = int(input("请输入课程代号:"))
if course_index not in codes:
print("您输入的代号不在范围内哦~")
else:
# 返回课程代号
return course_index
else:
up_or_down = input("上翻[up]/下翻[down]")[0].upper()
if up_or_down == "U":
cx_driver.swipe(self.screenWidth * 0.5, self.screenHeight * 0.25, self.screenWidth * 0.5,
self.screenHeight * 0.65, 500)
else:
cx_driver.swipe(self.screenWidth * 0.5, self.screenHeight * 0.65, self.screenWidth * 0.5,
self.screenHeight * 0.25, 500)
def page_processing_system(self):
base_xpath = "//android.webkit.WebView/android.webkit.WebView/android.view.View"
self.wait_element_by_xpath(base_xpath, 3)
# 计数器
num = 0
# 获取可能目标
base_ls = cx_driver.find_elements_by_xpath(base_xpath)
for i in base_ls:
location_xpath = "//android.webkit.WebView/android.webkit.WebView/android.view.View[%s]/android.view.View[1]" % base_ls.index(
i)
is_finish_xpath = "//android.webkit.WebView/android.webkit.WebView/android.view.View[%s]/android.view.View[2]" % base_ls.index(
i)
TAG_xpath = "//android.webkit.WebView/android.webkit.WebView/android.view.View[%s]" % (base_ls.index(i) - 1)
not_TAG_xpath = "//android.webkit.WebView/android.webkit.WebView/android.view.View[%s]/android.view.View" % (
base_ls.index(i) - 1)
location = self.is_element_xpath_exist(location_xpath)
tag = self.is_element_xpath_exist(TAG_xpath)
not_tag = self.is_element_xpath_exist(not_TAG_xpath)
finished = self.is_element_xpath_exist(is_finish_xpath)
# 从可能目标中选取未完成任务点,并排除大部分已完成任务点
if location and tag and (not not_tag) and (not finished):
# 筛选未完成任务点
if "已" not in cx_driver.find_element_by_xpath(TAG_xpath).get_attribute("text"):
play_xpath = "//android.webkit.WebView/android.webkit.WebView/android.view.View[%s]/android.view.View/android.view.View/android.view.View/android.widget.Image" % base_ls.index(
i)
# 如果该未完成任务点可以播放,证明是未完成视频,放入未完成视频列表
if self.is_element_xpath_exist(play_xpath):
if self.cx_crawl_vedio_play(play_xpath):
num += 1
continue
# 如果该未完成任务点不能播放,证明是测试题,给出提示
else:
print("这是测试题,记得做哦~")
print("已处理%s个未完成视频" % num)
print("该页面处理完成")
back_id = "com.chaoxing.mobile:id/iv_chapter_back"
WebDriverWait(cx_driver, 10).until(EC.element_to_be_clickable((By.ID, back_id)),
message='timeout').click()
此处将 刷视频函数 从 主循环 挪到 单页面任务点处理函数
所以对 主循环 进行修改,并删除 判断是否完成函数
def start_main_circullation(self):
class_list_xpath = "//android.widget.RelativeLayout/android.support.v7.widget.RecyclerView/android.widget.RelativeLayout"
back_id = "com.chaoxing.mobile:id/iv_chapter_back"
# 设置主循环变量
m = 1
# 主循环
while m:
num = len(cx_driver.find_elements_by_xpath(class_list_xpath)) - 1
print("准备!")
# 设置B循环变量
n = 1
# 设置已爬取列表
curScreenItemSet = []
# B循环:单页爬虫核心循环,去头去尾
while n < num:
try:
# 爬取当前页面
ls = self.cx_crawl_main_list(class_list_xpath)
# 取页面第n个小节
sleep(0.5)
identification = ls[n].find_element_by_id("com.chaoxing.mobile:id/tv_sub_index").get_attribute(
'text')
print("看看课程%s.^v^." % identification)
# 该课程的一系列操作
if identification not in curScreenItemSet:
print("哎 这个可以!")
# 点进去
self.cx_crawl_point_in(n)
while True:
try:
print("等它加载一下")
top_title_xpath = "com.chaoxing.mobile:id/tv_chapter_name"
self.wait_element_by_id(top_title_xpath, 5)
# 查是否空白页
if self.cx_crawl_is_white(back_id):
curScreenItemSet.append(identification)
n += 1
continue
# 确定视频位置
self.cx_crawl_vedio_where()
# 单面任务点处理
self.page_processing_system()
n += 1
break
except Exception as e:
print(e)
else:
print("这个看过了哦~")
except Exception as e:
n += 1
print(e)
print("这个不行欸,怎么办怎么办x_x 算啦,还是看看下面的吧~")
# 滑动,下一页
cx_driver.swipe(self.screenWidth * 0.5, self.screenHeight * 0.65, self.screenWidth * 0.5,
self.screenHeight * 0.25, 500)
sleep(0.5)
并且因增加多视频功能,视频播放按钮不唯一,改写视频播放函数部分内容:
def cx_crawl_vedio_play(self, Play_button_xpath):
pass # 初始版本中有讲解
from appium import webdriver
from time import sleep
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from appium.webdriver.common.touch_action import TouchAction
class CxAuto:
def __init__(self):
self.desired_caps = { # 启动数据
"platformName": "Android",
"platformVersion": "7.1.2",
"deviceName": "127.0.0.1:62025",
"newCommandTimeout": "60000",
"appPackage": "com.chaoxing.mobile",
"appActivity": ".activity.SplashActivity",
"noReset": "True"
}
self.cx_driver = self.cx_open() # 调用启动函数,打开app
self.course_index = -1 # 设要刷课程为第-1个课程,即默认开启选课模式
self.screenWidth = self.cx_driver.get_window_size()["width"]
self.screenHeight = self.cx_driver.get_window_size()["height"]
def cx_open(self): # 调用启动数据进行启动函数
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', self.desired_caps)
print("打开超星APP啦!")
return driver
def is_element_xpath_exist(self, x_path): # 工具函数
if not self.cx_driver.find_elements_by_xpath(x_path):
return False
else:
return True
def is_element_id_exist(self, x_id): # 工具函数
if not self.cx_driver.find_elements_by_id(x_id):
return False
else:
return True
def wait_element_by_xpath(self, x_path, sleep_time): # 工具函数
while True:
try:
while self.is_element_xpath_exist(x_path=x_path):
return True
else:
print("等待中...")
sleep(int(sleep_time))
except Exception as e:
print(e)
def wait_element_by_id(self, x_id, sleep_time): # 工具函数
while True:
try:
while self.is_element_id_exist(x_id=x_id):
return True
else:
print("等待中...")
sleep(int(sleep_time))
except Exception as e:
print(e)
def num_of_xpath(self, x_path): # 工具函数
if not self.is_element_xpath_exist(x_path):
return 0
return len(self.cx_driver.find_elements_by_xpath(x_path))
def start_point_me(self): # 点击函数
# 点击我
wo_xpath = "//android.widget.RelativeLayout[4]"
if self.wait_element_by_xpath(wo_xpath, 5):
WebDriverWait(self.cx_driver, 20).until(EC.element_to_be_clickable((By.XPATH, wo_xpath)),
message='timeout').click()
print("看看我的主页~")
def start_point_class(self): # 点击函数
# 点击课程
course_xpath = "com.chaoxing.mobile:id/myCourse"
if self.wait_element_by_id(course_xpath, 5):
WebDriverWait(self.cx_driver, 20).until(EC.element_to_be_clickable((By.ID, course_xpath)),
message='timeout').click()
print("看看我的课程~")
def start_choose_course(self): # 选课函数
while True:
course_xpath = "//android.widget.RelativeLayout/android.support.v7.widget.RecyclerView/android.widget.FrameLayout"
self.wait_element_by_xpath(course_xpath, 5)
courses = self.cx_driver.find_elements_by_xpath(course_xpath)
codes = []
for course in courses:
course_name = course.find_element_by_id("com.chaoxing.mobile:id/tv_name").get_attribute("text")
course_code = int(courses.index(course)) + 1
codes.append(course_code)
print(course_code, " -- ", course_name)
is_eligible = input("这些课程有合您心意吗?[True/False]")[0].upper()
if is_eligible == "T":
while True:
course_index = int(input("请输入课程代号:"))
if course_index not in codes:
print("您输入的代号不在范围内哦~")
else:
return course_index
else:
up_or_down = input("上翻[up]/下翻[down]")[0].upper()
if up_or_down == "U":
self.cx_driver.swipe(self.screenWidth * 0.5, self.screenHeight * 0.25, self.screenWidth * 0.5,
self.screenHeight * 0.65, 500)
else:
self.cx_driver.swipe(self.screenWidth * 0.5, self.screenHeight * 0.65, self.screenWidth * 0.5,
self.screenHeight * 0.25, 500)
def start_point_course(self): # 点击函数
if self.course_index == -1:
self.course_index = self.start_choose_course()
# 点击具体课程
course_xpath = "//android.widget.RelativeLayout/android.support.v7.widget.RecyclerView/android.widget.FrameLayout[%s]" % self.course_index
if self.wait_element_by_xpath(course_xpath, 5):
WebDriverWait(self.cx_driver, 10).until(EC.element_to_be_clickable((By.XPATH, course_xpath)),
message='timeout').click()
print("打开课程,开始了哦")
def start_point_course_section(self): # 点击函数
# 点击章节所在页
class_page_xpath = "//android.widget.LinearLayout[1]/android.widget.FrameLayout[2]/android.widget.TextView"
if self.wait_element_by_xpath(class_page_xpath, 5):
WebDriverWait(self.cx_driver, 10).until(EC.element_to_be_clickable((By.XPATH, class_page_xpath)),
message='timeout').click()
def cx_crawl_main_list(self, class_list_xpath): # 主循环逻辑处理函数
print("让我再看看列表,没看仔细,5~")
WebDriverWait(self.cx_driver, 20).until(EC.element_to_be_clickable((By.XPATH, class_list_xpath)),
message='timeout')
sleep(1)
ls = self.cx_driver.find_elements_by_xpath(class_list_xpath)
return ls
def cx_crawl_point_in(self, n): # 主循环逻辑处理函数
WebDriverWait(self.cx_driver, 20).until(EC.element_to_be_clickable(
(By.XPATH,
"//android.widget.RelativeLayout/android.support.v7.widget.RecyclerView/android.widget.RelativeLayout[{}]".format(
n + 1))),
message='timeout').click()
def cx_crawl_is_white(self, back_id): # 主循环逻辑处理函数
# 空页处理
white_xpath = "//android.support.v4.view.ViewPager/android.widget.RelativeLayout/android.widget.TextView"
white_con_xpath = "//android.webkit.WebView/android.webkit.WebView/android.view.View[1]"
v4_id = "com.chaoxing.mobile:id/vp_chapter"
self.wait_element_by_id(v4_id, 3)
sleep(2)
p = self.is_element_xpath_exist(white_xpath)
q = "暂无内容" in self.cx_driver.find_element_by_xpath(white_con_xpath).get_attribute(
"text") if self.is_element_xpath_exist(white_con_xpath) else 1
if p or q:
print("这个居然是空 白 页,天哪,快回快回@x@")
WebDriverWait(self.cx_driver, 10).until(EC.element_to_be_clickable((By.ID, back_id)),
message='timeout').click()
sleep(0.5)
return 1
return 0
def cx_crawl_vedio_where(self): # 主循环逻辑处理函数
title_id = "com.chaoxing.mobile:id/tb_chapter"
title_xpath = "//android.widget.LinearLayout/android.support.v7.app.ActionBar.Tab"
sleep(2)
if self.is_element_id_exist(title_id):
WebDriverWait(self.cx_driver, 20).until(EC.element_to_be_clickable((By.XPATH, title_xpath)),
message='timeout')
# 判断是否是标题,是标题则处理
if self.is_element_xpath_exist(title_xpath + "[3]"):
print("我知道!这是标题课,对不对?^z^")
# 如果有第三个证明是标题,判断数量4-3,3-2
title_num = len(self.cx_driver.find_elements_by_xpath(title_xpath))
if title_num == 3:
WebDriverWait(self.cx_driver, 10).until(
EC.element_to_be_clickable((By.XPATH, title_xpath + "[2]")),
message='timeout').click()
else:
WebDriverWait(self.cx_driver, 10).until(
EC.element_to_be_clickable((By.XPATH, title_xpath + "[3]")),
message='timeout').click()
def page_processing_system(self): # 主循环逻辑处理函数
base_xpath = "//android.webkit.WebView/android.webkit.WebView/android.view.View"
self.wait_element_by_xpath(base_xpath, 3)
# 计数器
num = 0
# 获取可能目标
base_ls = self.cx_driver.find_elements_by_xpath(base_xpath)
for i in base_ls:
location_xpath = "//android.webkit.WebView/android.webkit.WebView/android.view.View[%s]/android.view.View[1]" % base_ls.index(
i)
is_finish_xpath = "//android.webkit.WebView/android.webkit.WebView/android.view.View[%s]/android.view.View[2]" % base_ls.index(
i)
tag_xpath = "//android.webkit.WebView/android.webkit.WebView/android.view.View[%s]" % (base_ls.index(i) - 1)
not_tag_xpath = "//android.webkit.WebView/android.webkit.WebView/android.view.View[%s]/android.view.View" % (
base_ls.index(i) - 1)
location = self.is_element_xpath_exist(location_xpath)
tag = self.is_element_xpath_exist(tag_xpath)
not_tag = self.is_element_xpath_exist(not_tag_xpath)
finished = self.is_element_xpath_exist(is_finish_xpath)
# 从可能目标中选取未完成任务点,并排除大部分已完成任务点
if location and tag and (not not_tag) and (not finished):
# 筛选未完成任务点
if "已" not in self.cx_driver.find_element_by_xpath(tag_xpath).get_attribute("text"):
play_xpath = "//android.webkit.WebView/android.webkit.WebView/android.view.View[%s]/android.view.View/android.view.View/android.view.View/android.widget.Image" % base_ls.index(
i)
# 如果该未完成任务点可以播放,证明是未完成视频,放入未完成视频列表
if self.is_element_xpath_exist(play_xpath):
if self.cx_crawl_vedio_play(play_xpath):
num += 1
continue
# 如果该未完成任务点不能播放,证明是测试题,给出提示
else:
print("这是测试题,记得做哦~")
print("已处理%s个未完成视频" % num)
print("该页面处理完成")
back_id = "com.chaoxing.mobile:id/iv_chapter_back"
WebDriverWait(self.cx_driver, 10).until(EC.element_to_be_clickable((By.ID, back_id)),
message='timeout').click()
def cx_crawl_vedio_play(self, play_button_xpath): # 主循环逻辑处理函数
print("开始播放了哦~")
retry_id = "com.chaoxing.mobile:id/btnOk"
content_id = "com.chaoxing.mobile:id/test_tv_question"
dui_xpath = "//android.support.v7.widget.RecyclerView/android.widget.LinearLayout[1]"
cuo_xpath = "//android.support.v7.widget.RecyclerView/android.widget.LinearLayout[2]"
go_id = "com.chaoxing.mobile:id/btn_check_answer"
next_id = "com.chaoxing.mobile:id/btn_next"
check_id = "com.chaoxing.mobile:id/tv_answer"
back_id = "com.chaoxing.mobile:id/iv_chapter_back"
interface_id = "com.chaoxing.mobile:id/surface_container"
# 点击播放按钮
WebDriverWait(self.cx_driver, 15).until(
EC.element_to_be_clickable((By.XPATH, play_button_xpath)),
message='timeout').click()
# 点击重试
sleep(15)
if self.is_element_id_exist(retry_id):
WebDriverWait(self.cx_driver, 60).until(EC.element_to_be_clickable((By.ID, retry_id)),
message='timeout').click()
print("小脚本为您持续监测...")
# 设置检测循环
while True:
try:
# 等待时间
sleep(30)
if self.is_element_id_exist(content_id):
print("答题~!")
print("努力回魂中,稍微等一下哦~")
WebDriverWait(self.cx_driver, 10).until(
EC.element_to_be_clickable((By.ID, content_id)),
message='timeout')
# 点击对
WebDriverWait(self.cx_driver, 10).until(
EC.element_to_be_clickable((By.XPATH, dui_xpath)),
message='timeout').click()
# 点击提交
WebDriverWait(self.cx_driver, 10).until(EC.element_to_be_clickable((By.ID, go_id)),
message='timeout').click()
sleep(0.5)
# 检查是否正确
if "正确" in WebDriverWait(self.cx_driver, 10).until(
EC.element_to_be_clickable((By.ID, check_id)),
message='timeout').get_attribute("text"):
# 点击继续
if self.is_element_id_exist(next_id):
WebDriverWait(self.cx_driver, 10).until(
EC.element_to_be_clickable((By.ID, next_id)),
message='timeout').click()
if self.is_element_id_exist(go_id):
WebDriverWait(self.cx_driver, 10).until(
EC.element_to_be_clickable((By.ID, go_id)),
message='timeout').click()
else:
# 点击错
WebDriverWait(self.cx_driver, 10).until(
EC.element_to_be_clickable((By.XPATH, cuo_xpath)),
message='timeout').click()
# 点击提交
if self.is_element_id_exist(go_id):
WebDriverWait(self.cx_driver, 10).until(
EC.element_to_be_clickable((By.ID, go_id)),
message='timeout').click()
if self.is_element_id_exist(next_id):
WebDriverWait(self.cx_driver, 10).until(
EC.element_to_be_clickable((By.ID, next_id)),
message='timeout').click()
elif self.is_element_id_exist(back_id):
# 视频播放完会自动回到页面,等回退按钮出来后证明视频已看完
print("完成啦!下一个")
sleep(0.5)
return 1
elif self.is_element_id_exist(retry_id):
print("网络或app出错,等待连接中...")
while self.is_element_id_exist(retry_id):
sleep(5)
WebDriverWait(self.cx_driver, 10).until(
EC.element_to_be_clickable((By.ID, retry_id)),
message='timeout').click()
print("成功重新连接,恢复中,稍等哦~")
interface = self.cx_driver.find_element_by_id(interface_id)
TouchAction(self.cx_driver).press(el=interface, pressure=0.25).release().perform()
else:
print("我还没挂,吱个声 嘻嘻^v^")
except Exception as e:
print(e)
print("出错啦! 是不是没网了")
def start_main_circullation(self): # 主循环
class_list_xpath = "//android.widget.RelativeLayout/android.support.v7.widget.RecyclerView/android.widget.RelativeLayout"
back_id = "com.chaoxing.mobile:id/iv_chapter_back"
# 设置主循环变量
m = 1
# 主循环
while m:
num = len(self.cx_driver.find_elements_by_xpath(class_list_xpath)) - 1
print("准备!")
# 设置B循环变量
n = 1
# 设置已爬取列表
cur_screen_item_set = []
# B循环:单页爬虫核心循环,去头去尾
while n < num:
try:
# 爬取当前页面
ls = self.cx_crawl_main_list(class_list_xpath)
# 取页面第n个小节
sleep(0.5)
identification = ls[n].find_element_by_id("com.chaoxing.mobile:id/tv_sub_index").get_attribute(
'text')
print("看看课程%s.^v^." % identification)
# 该课程的一系列操作
if identification not in cur_screen_item_set:
print("哎 这个可以!")
# 点进去
self.cx_crawl_point_in(n)
while True:
try:
print("等它加载一下")
top_title_xpath = "com.chaoxing.mobile:id/tv_chapter_name"
self.wait_element_by_id(top_title_xpath, 5)
# 查是否空白页
if self.cx_crawl_is_white(back_id):
cur_screen_item_set.append(identification)
n += 1
break
# 确定视频位置
self.cx_crawl_vedio_where()
# 单面任务点处理
self.page_processing_system()
n += 1
break
except Exception as e:
print(e)
else:
print("这个看过了哦~")
except Exception as e:
n += 1
print(e)
print("这个不行欸,怎么办怎么办x_x 算啦,还是看看下面的吧~")
# 滑动,下一页
sleep(1)
self.cx_driver.swipe(self.screenWidth * 0.5, self.screenHeight * 0.65, self.screenWidth * 0.5,
self.screenHeight * 0.25, 500)
sleep(0.5)
def start(): # 可自定义动作的开始函数
go_go_go = CxAuto() # 假设我要刷的课在课表的第五行,读者也可以进行改动用名称来定位
go_go_go.start_point_me()
go_go_go.start_point_class()
go_go_go.start_point_course()
go_go_go.start_point_course_section()
go_go_go.start_main_circullation()
if __name__ == '__main__': # 主线程
start()
【转载请注明出处】