租了一台服务器,今天终于派上了用场---刷智慧树的网课。
其实,这话有点夸大了,是刷视频。
一、环境:python3.* selenium chrome chromedriver windows10
二、程序功能:
输入课程号,(手动)登录智慧树, 然后程序播放课程下的视频,将进步发送给自己微信助手。
三、程序:
(1)智慧树刷课
[Python] 纯文本查看 复制代码 """
智慧树刷课
https://www.zhihuishu.com/
"""
from selenium import webdriver
import time
import random
import re
import wechat
from retrying import retry
import easygui as g
# 设置输出方式, 进度发送到微信
def output( code="" ):
print( code )
app.send( code )
class zhihuishu_sprider():
def __init__(self, account, password, school_name, class_name ):
self.account = account
self.password = password
self.school_name = school_name
self.class_name = class_name
opt= webdriver.ChromeOptions()
opt.add_argument("--no-sandbox")
self.driver = webdriver.Chrome( options= opt )
self.url = "https://passport.zhihuishu.com/login?service=https://onlineservice.zhihuishu.com/login/gologin"
self.stu_url = "https://onlineh5.zhihuishu.com/onlineWeb.html#/studentIndex"
# 写cookies
def write(self):
cookies = self.driver.get_cookies()
cookies_list = []
for item in cookies:
cookie_dict = {}
cookie_dict["name"] = str(item["name"])
cookie_dict["value"] = str(item["value"])
cookies_list.append( cookie_dict )
with open("cookies.txt", "w" , encoding="utf-8") as f:
f.write(str( cookies_list))
# 读取cookeis
def read(self):
try:
with open("cookies.txt", "r", encoding="utf-8") as f:
cookies = f.read()
cookies = eval( cookies )
for item in cookies:
print( item , type(item ))
self.driver.add_cookie( item )
except Exception as e:
print(e )
def _sign(self):
# self.read()
# self.driver.get( self.stu_url )
# self.read()
self.driver.get( self.stu_url )
if not self.driver.current_url == self.stu_url:
self.driver.delete_all_cookies()
self.driver.get( self.url )
# todo 自动登录暂时无法解决, 需要模拟驱动
js = """
$("#lUsername").val("15293217483");
"""
self.driver.execute_script( js )
ans = input("输入任意键,代表登录完成!")
if self.driver.current_url == self.stu_url:
return True
return False
# 打开课程, 返回课程url
def open_class(self):
class_url = self.driver.current_url
self.driver.get( class_url )
# 获取课程列表,选择课程
class_list = self.driver.find_elements_by_xpath("//*[@id='sharingClassed']/div[2]/ul")
for item in class_list:
class_title = item.find_element_by_xpath("div/dl/dt/div[1]").text
print( class_title )
if self.class_name in class_title:
item.find_element_by_xpath("div/dl/dt/div[1]").click()
for i in range(10):
time.sleep(1)
url = self.driver.current_url
if not url == class_url:
return url
break
return ""
@retry( stop_max_attempt_number=10)
# 观看视频, 弹出框--警示框、答题框
def view_class( self, class_url ):
self.driver.get( class_url )
# 如果警告存在,则关闭警告
for i in range(5):
warnning_btn = self.driver.find_elements_by_xpath("//*[@id='app']/div/div[6]/div/div[3]/span/button/span")
try:
if warnning_btn:
warnning_btn[0].click()
break
except:
pass
time.sleep(1)
# 如果学前必读提示存在,怎关闭提示
for i in range(5):
warnning_btn = self.driver.find_elements_by_xpath("//*[@id='app']/div/div[7]/div[2]/div[1]/i")
try:
if warnning_btn:
warnning_btn[0].click()
break
time.sleep(1)
except:
pass
# 选择章节
# charp_list = self.driver.find_elements_by_xpath("//*[@id='app']/div/div[2]/div[2]/div[2]/div[1]//div" )
# charp_list = self.driver.find_elements_by_xpath("//*[@id='app']/div/div[2]/div[2]//div/span")
charp_list = self.driver.find_elements_by_class_name("cataloguediv-c")
# 找到没有看的视频
## (1) //span[2]: n.n.n类型的时间; (2)// span[1] n.n型, 标题和时间在一起
# text: 标题 + 播放时间
for i in range(len(charp_list) ):
charp_list = self.driver.find_elements_by_class_name("cataloguediv-c")
item = charp_list[i]
text = str(item.text).replace("\n","").strip()
try:
video_leng = re.search(r"\d{2}:\d{2}:\d{2}", text).group()
except Exception as e:
video_leng = ""
if video_leng :
finsh_img = item.find_elements_by_class_name("time_icofinish")
if finsh_img:
# print( finsh_img[0].get_attribute('innerHTML') )
output( text[:-8]+"已播放完成!")
continue
item.find_element_by_xpath("span").click()
time.sleep( random.randint(1,4) )
video_leng = video_leng.split(":")
video_leng = int(video_leng[0])*60*60+int(video_leng[1])*60+int(video_leng[2])
output(text[:-8]+"开始播放")
output("\t播放时长:"+ str( video_leng) )
# 使用js 播放视频
js = """
$item = $("#playButton");
if( $item.prop("class") == "playButton"){
$item.click();
}
"""
self.driver.execute_script( js )
## 随机弹出答题框 //*[@id="app"]/div/div[7]/div
# A 选项 //*[@id="app"]/div/div[7]/div/div[2]/div/div[1]/div/div/div[2]/ul/li[1]
# B 选项 //*[@id="app"]/div/div[7]/div/div[2]/div/div[1]/div/div/div[2]/ul/li[2]
# 关闭按钮://*[@id="app"]/div/div[7]/div/div[3]/span/div
for i in range( video_leng +5):
popup = self.driver.find_elements_by_xpath( "//*[@id='app']/div/div[7]/div")
if popup:
try:
self.driver.find_element_by_xpath("//*[@id='app']/div/div[7]/div/div[2]/div/div[1]/div/div/div[2]/ul/li[{}]"
.format(str( random.randint(1,2)))).click()
time.sleep( random.randint(1,3))
self.driver.find_element_by_xpath("//*[@id='app']/div/div[7]/div/div[3]/span/div").click()
except :
pass
time.sleep(1)
self.driver.execute_script( js )
time.sleep( random.randint(1,3) )
output("\t\t播放结束!")
def run(self ):
if self._sign():
output("登录成功!")
class_url = self.open_class( )
if class_url:
self.view_class( class_url )
else:
print("class_url", class_url)
self.write()
else:
output("登录失败, 从新开始!")
if __name__ == '__main__':
info = g.multenterbox( msg="请填写信息", fields=['课程号'], values=["创践——大学生创新创业实务"])
if len(info):
sprider = zhihuishu_sprider("******","****", "*****",str( info[0]))
app = wechat.wechat_app()
sprider.run()
(2)网页微信(这个其实没有什么可说的)
[Python] 纯文本查看 复制代码 """
微信登录,发送消息
"""
import itchat
class wechat_app():
def __init__(self):
self.app =itchat
self.app.auto_login( hotReload=True )
print("微信, 登录成功!")
def send(self, code):
self.app.send( code, 'filehelper' )
四、存在的问题:
(1)无法自动登录:利用js 或者 send_key() 会出现滚动条, 而这个滚动条即使是手动也没有办法验证成功。
我怀疑它是绑定了keydown监听事件, 如果不出现keydown事件,那么就基本不拒绝了。因为上面两种方法都不会触发keydown事件。
(2)太多太多太多的try、except
|