【仅供交流学习使用,转载请注明出处】
真的仅供交流学习使用…
准备工具:windows系统,python编译器,selenium包,pythonIDE(推荐jupyter notebook,笔者使用的是pycharm),appium,模拟器(笔者使用的是nox),Android SDK,java JDK 网上有很多安装教程,这里笔者就不赘述了
【连真机也可以,但是炸了就不好玩了(滑稽)】
【小提示:安装selenium失败请加源,为方便读者---->清华源:https://pypi.tuna.tsinghua.edu.cn/simple】
安装完成后打开模拟器,在命令行中输入
adb connect 127.0.0.1:62001
这里说明一下,端口号一定要对齐,否则就会连接不上
夜神模拟器默认端口是62001,其他端口都以620开头,至于其他模拟器端口网上都可以查到
如果你增添了模拟器那么你要连接的就不一定是62001了,端口号可以通过以下代码查看:
netstat -ano |findstr 620
然后我们在appium上开启服务(记下端口号默认是4723)
ok,一切就绪准备开始吧
首先我们在Nox上安装学习通
打开cmd(或shell),输入:
adb shell
然后在打开学习通瞬间在adb shell中输入并回车:
dumpsys activity | grep mFocusedActivity
如果你多试几次,结果应该如下:
C:\Users\Administrator>adb shell
R17:/ # dumpsys activity | grep mFocusedActivity
mFocusedActivity: ActivityRecord{e2f77e8 u0 com.vphone.launcher/.Launcher t2}
R17:/ # dumpsys activity | grep mFocusedActivity
mFocusedActivity: ActivityRecord{add4c1c u0 com.chaoxing.mobile/.activity.SplashActivity t21}
R17:/ # dumpsys activity | grep mFocusedActivity
mFocusedActivity: ActivityRecord{9b9f64e u0 com.chaoxing.mobile/.activity.DoodleActivity t21}
R17:/ # dumpsys activity | grep mFocusedActivity
mFocusedActivity: ActivityRecord{8c0765f u0 com.chaoxing.mobile/.main.ui.MainTabActivity t21}
R17:/ #
第一个是还没打开,第二个是学习通app的发起入口,第三个是广告界面,第四个就是主界面了,这里我们只需要第二个。
其中com.chaoxing.mobile代表学习通app
.activity.SplashActivity代表打开的动作。
然后我们就可以在IDE中及其快(tong)乐(ku)地coding了
引入库:
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
设置帽子:
desired_caps = {
"platformName": "Android", # 这个就不解释了
"platformVersion": "7.1.2", # 安卓系统版本号
"deviceName": "127.0.0.1:62025", # 默认是安卓5,笔者选了安卓7后端口号发生改变
"newCommandTimeout": "60000", # 设置多少秒后停止,防止它突然暴毙
"appPackage": "com.chaoxing.mobile", # 谁:学习通的"名字"
"appActivity": ".activity.SplashActivity", # 动作:打开它
"noReset": "True" # 是否缓存,为了防止每次登录都要输一遍密码就开缓存
}
然后我们执行上面的帽子:
def cx_open():
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
print("打开超星APP啦!")
return driver
cx_driver = cx_open()
笔者使用cx_driver代指打开超星学习通,之后的操作我们也围绕着它进行
首先我们理一下思路,如何实现自动化
通常我们去看学习通中的一个视频的流程是这样的:
前面我们已经打开了学习通app,下面我们就定义一个操作学习通的类
class CxAuto:
def __init__(self): # 定义类的"全局"变量
pass
def start_point_me(self): # 点击我
pass
def start_point_class(self): # 点击课程
pass
def start_point_course(self): # 点击具体哪一门课
pass
def start_point_course_section(self): # 点击章节
pass
def start_main_circullation(self): # 不停地刷视频
pass
好,以上是一个粗略的框架
def __init__(self, course_index):
self.course_index = course_index # 指定课程的下标,如何使用见下文
self.screenWidth = cx_driver.get_window_size()["width"] # 用于以后滑屏
self.screenHeight = cx_driver.get_window_size()["height"]
然后我们打开appium,点击appium中类似放大镜的按钮,即Start Inspector session,将以上的帽子输入并保存,然后运行,此时你会看到超星学习通又被打开一次,appium会弹出一个界面,这是用来帮助定位的。
def is_element_xpath_exist(self, x_path): # 判断某xpath下的元素是否存在
if cx_driver.find_elements_by_xpath(x_path) == []:
return False
else:
return True
def is_element_id_exist(self, x_id): # 判断某id下的元素是否存在
if cx_driver.find_elements_by_id(x_id) == []:
return False
else:
return True
def wait_element_by_xpath(self, x_path, sleep_time): # 等待某xpath元素出现
while True:
try: # 有时候这里等着等着连接就断了,需要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): # 等待某id元素出现
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 start_point_me(self):
# 点击我
wo_xpath = "//android.widget.RelativeLayout[4]"
if self.wait_element_by_xpath(wo_xpath, 5):
WebDriverWait(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(cx_driver, 20).until(EC.element_to_be_clickable((By.ID, course_xpath)),
message='timeout').click()
print("看看我的课程~")
def start_point_course(self):
# 点击具体课程
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_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(cx_driver, 10).until(EC.element_to_be_clickable((By.XPATH, class_page_xpath)),
message='timeout').click()
接下来我们就要写刷视频的核心代码了,可以肯定它是一个循环,虽然不知道是否有什么其他情况
def start_main_circullation(self):
class_list_xpath = "//android.widget.RelativeLayout/android.support.v7.widget.RecyclerView/android.widget.RelativeLayout"
# 返回键的id
back_id = "com.chaoxing.mobile:id/iv_chapter_back"
# 设置主循环变量
m = 1
# 设置开始变量 如果用户有需求可以从某节开始,因代码较少,功能较次,为读者看的清楚就不放出来了
k = 0
# 主循环
while m:
num = len(cx_driver.find_elements_by_xpath(class_list_xpath)) - 1
print("准备!")
# 设置B循环变量
n = 1
# 设置已爬取列表(防止看了一遍,又去看一遍)
curScreenItemSet = []
# B循环:单页爬虫核心循环,去头去尾(手机中通常有卡一半的按钮,这个我们就不要了)
while n < num:
pass # 待完善
# 滑动,下一页
cx_driver.swipe(self.screenWidth * 0.5, self.screenHeight * 0.65, self.screenWidth * 0.5,
self.screenHeight * 0.25, 500)
sleep(0.5)
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("欸~ 这个可以!")
pass # 劈里啪啦一顿操作就把这个看完了
#返回列表的代码放到看视频完成的地方,这样可以避免很多麻烦
这里有个获取列表的函数,就是把当前页面上的元素装进列表里,每点进去一次该列表指向就会发生改变,通俗地说就是失效,这时我们必须重新获取,也是将它写成函数的重要原因,具体代码如下:
def cx_crawl_main_list(self, class_list_xpath):
print("让我再看看列表,没看仔细,5~")
WebDriverWait(cx_driver, 20).until(EC.element_to_be_clickable((By.XPATH, class_list_xpath)),
message='timeout')
sleep(1)
ls = cx_driver.find_elements_by_xpath(class_list_xpath)
return ls
if identification not in curScreenItemSet:
print("欸~ 这个可以!")
# 点进去
self.cx_crawl_point_in(n)
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()
temporary_xpath = "//android.webkit.WebView/android.webkit.WebView/android.view.View"
self.wait_element_by_xpath(temporary_xpath, 5)
print("稍微等等,我怕没加载完^x^")
# 判断是否已完成
if self.cx_crawl_is_finish():
curScreenItemSet.append(identification)
n += 1
continue
print("开始播放了哦~")
if self.cx_crawl_vedio_play():
curScreenItemSet.append(identification)
n += 1
except Exception as e:
print(e)
else:
print("这个看过了哦~")
这里面我用了很多未定义函数,为的就是理清思路【其实只是为了好看(时而滑稽之)】
下面我们对每一个函数冠以cx_crawl的前缀进行定义:
def cx_crawl_point_in(self, n):
#这里注意下标,具体的可以根据appium来定位和寻找下表规律
WebDriverWait(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 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(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(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(cx_driver.find_elements_by_xpath(title_xpath))
if title_num == 3:
WebDriverWait(cx_driver, 10).until(
EC.element_to_be_clickable((By.XPATH, title_xpath + "[2]")),
message='timeout').click()
else:
WebDriverWait(cx_driver, 10).until(
EC.element_to_be_clickable((By.XPATH, title_xpath + "[3]")),
message='timeout').click()
因为是操作函数,不需要返回值
这时已经可以确定视频就在当前界面,同时学习通会指明你是否看过视频,它的标识就是我们判断的依据
不幸的是,这个标识也有三种情况,而且完全随机,见代码中的a和b
def cx_crawl_is_finish(self):
sleep(1.5)
base_xpath = "//android.webkit.WebView/android.webkit.WebView/android.view.View"
if self.wait_element_by_xpath(base_xpath, 3):
a = self.is_element_xpath_exist(
"//android.webkit.WebView/android.webkit.WebView/android.view.View[1]/android.view.View[1]")
b = self.is_element_xpath_exist(
"//android.webkit.WebView/android.webkit.WebView/android.view.View[2]/android.view.View[1]")
c = self.is_element_xpath_exist(
"//android.webkit.WebView/android.webkit.WebView/android.view.View[2]/android.view.View[1]/android.view.View")
if a or (b and not c):
# 确定已经完成无疑了,回去
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()
print("哎,看来这个已经完成了~")
sleep(0.5)
return 1
return 0
最后的最后就是我们的播放函数了,学习通的视频似乎有反爬,第一次无论如何也加载不出来,等它弹出是否重新加载时点击是就瞬间好了。。。
最好(gou)的是视频不仅不能倍速不能快进而且在中间还会有答题,就卡在那里了,好在基本上都是判断题。
分析学习通视频特点:
思路:全选对,提交,错了那就再选错,提交
def cx_crawl_vedio_play(self):
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"
# 点击播放按钮
Play_button_xpath = "//android.view.View/android.view.View/android.widget.Image"
WebDriverWait(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(cx_driver, 60).until(EC.element_to_be_clickable((By.ID, retry_id)),
message='timeout').click()
print("小脚本为您持续监测...")
# 设置检测循环
while True:
try:
# 等待时间
sleep(60)
if self.is_element_id_exist(content_id):
print("答题~!")
WebDriverWait(cx_driver, 10).until(
EC.element_to_be_clickable((By.ID, content_id)),
message='timeout')
# 点击对
WebDriverWait(cx_driver, 10).until(
EC.element_to_be_clickable((By.XPATH, dui_xpath)),
message='timeout').click()
# 点击提交
WebDriverWait(cx_driver, 10).until(EC.element_to_be_clickable((By.ID, go_id)),
message='timeout').click()
sleep(0.5)
# 检查是否正确
if "正确" in WebDriverWait(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(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(cx_driver, 10).until(
EC.element_to_be_clickable((By.ID, go_id)),
message='timeout').click()
else:
# 点击错
WebDriverWait(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(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(cx_driver, 10).until(
EC.element_to_be_clickable((By.ID, next_id)),
message='timeout').click()
elif self.is_element_id_exist(back_id):
# 视频播放完会自动回到页面,等回退按钮出来后就点击回退按钮
WebDriverWait(cx_driver, 10).until(EC.element_to_be_clickable((By.ID, back_id)),
message='timeout').click()
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(cx_driver, 10).until(
EC.element_to_be_clickable((By.ID, retry_id)),
message='timeout').click()
print("成功重新连接,恢复中,稍等哦~")
interface = cx_driver.find_element_by_id(interface_id)
TouchAction(cx_driver).press(el=interface, pressure=0.25).release().perform()
else:
print("我还没挂,吱个声 嘻嘻^v^") # 捂脸...
except Exception as e:
print(e)
print("出错啦! 是不是没网了")
好了,到这里我们的刷视频CxAuto类就完成了
我们只需将各个部分整合即可得到我们想要的代码了
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
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"
}
def cx_open():
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
print("打开超星APP啦!")
return driver
cx_driver = cx_open()
class CxAuto:
def __init__(self, course_index):
self.course_index = course_index
self.screenWidth = cx_driver.get_window_size()["width"]
self.screenHeight = cx_driver.get_window_size()["height"]
def is_element_xpath_exist(self, x_path):
if cx_driver.find_elements_by_xpath(x_path) == []:
return False
else:
return True
def is_element_id_exist(self, x_id):
if 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 start_point_me(self):
# 点击我
wo_xpath = "//android.widget.RelativeLayout[4]"
if self.wait_element_by_xpath(wo_xpath, 5):
WebDriverWait(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(cx_driver, 20).until(EC.element_to_be_clickable((By.ID, course_xpath)),
message='timeout').click()
print("看看我的课程~")
def start_point_course(self):
# 点击具体课程
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_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(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(cx_driver, 20).until(EC.element_to_be_clickable((By.XPATH, class_list_xpath)),
message='timeout')
sleep(1)
ls = cx_driver.find_elements_by_xpath(class_list_xpath)
return ls
def cx_crawl_point_in(self, n):
WebDriverWait(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 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(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(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(cx_driver.find_elements_by_xpath(title_xpath))
if title_num == 3:
WebDriverWait(cx_driver, 10).until(
EC.element_to_be_clickable((By.XPATH, title_xpath + "[2]")),
message='timeout').click()
else:
WebDriverWait(cx_driver, 10).until(
EC.element_to_be_clickable((By.XPATH, title_xpath + "[3]")),
message='timeout').click()
def cx_crawl_is_finish(self):
sleep(1.5)
base_xpath = "//android.webkit.WebView/android.webkit.WebView/android.view.View"
if self.wait_element_by_xpath(base_xpath, 3):
a = self.is_element_xpath_exist(
"//android.webkit.WebView/android.webkit.WebView/android.view.View[1]/android.view.View[1]")
b = self.is_element_xpath_exist(
"//android.webkit.WebView/android.webkit.WebView/android.view.View[2]/android.view.View[1]")
c = self.is_element_xpath_exist(
"//android.webkit.WebView/android.webkit.WebView/android.view.View[2]/android.view.View[1]/android.view.View")
if a or (b and not c):
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()
print("哎,看来这个已经完成了~")
sleep(0.5)
return 1
return 0
def cx_crawl_vedio_play(self):
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"
# 点击播放按钮
Play_button_xpath = "//android.view.View/android.view.View/android.widget.Image"
WebDriverWait(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(cx_driver, 60).until(EC.element_to_be_clickable((By.ID, retry_id)),
message='timeout').click()
print("小脚本为您持续监测...")
# 设置检测循环
while True:
try:
# 等待时间
sleep(60)
if self.is_element_id_exist(content_id):
print("答题~!")
print("努力回魂中,稍微等一下哦~")
WebDriverWait(cx_driver, 10).until(
EC.element_to_be_clickable((By.ID, content_id)),
message='timeout')
# 点击对
WebDriverWait(cx_driver, 10).until(
EC.element_to_be_clickable((By.XPATH, dui_xpath)),
message='timeout').click()
# 点击提交
WebDriverWait(cx_driver, 10).until(EC.element_to_be_clickable((By.ID, go_id)),
message='timeout').click()
sleep(0.5)
# 检查是否正确
if "正确" in WebDriverWait(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(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(cx_driver, 10).until(
EC.element_to_be_clickable((By.ID, go_id)),
message='timeout').click()
else:
# 点击错
WebDriverWait(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(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(cx_driver, 10).until(
EC.element_to_be_clickable((By.ID, next_id)),
message='timeout').click()
elif self.is_element_id_exist(back_id):
# 视频播放完会自动回到页面,等回退按钮出来后就点击回退按钮
WebDriverWait(cx_driver, 10).until(EC.element_to_be_clickable((By.ID, back_id)),
message='timeout').click()
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(cx_driver, 10).until(
EC.element_to_be_clickable((By.ID, retry_id)),
message='timeout').click()
print("成功重新连接,恢复中,稍等哦~")
interface = cx_driver.find_element_by_id(interface_id)
TouchAction(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(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)
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()
temporary_xpath = "//android.webkit.WebView/android.webkit.WebView/android.view.View"
self.wait_element_by_xpath(temporary_xpath, 5)
print("稍微等等,我怕没加载完^x^")
# 判断是否已完成
if self.cx_crawl_is_finish():
curScreenItemSet.append(identification)
n += 1
continue
print("开始播放了哦~")
if self.cx_crawl_vedio_play():
curScreenItemSet.append(identification)
n += 1
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 start(n):
go_go_go = CxAuto(n) # 假设我要刷的课在课表的第五行,读者也可以进行改动用名称来定位
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(5)
好了,就讲这么多吧
公开发布,如果有大佬觉得尚有改进之处请在评论区留言
【仅供参考学习使用】
【更新:Python-Appium自动化测试-学习通自动刷视频(2)】