上海應(yīng)用大學(xué)網(wǎng)課自動(dòng)化學(xué)習(xí)腳本(基于Python selenium) —— 技術(shù)筆記
在閑暇線上學(xué)習(xí)中,網(wǎng)課平臺(tái)通常要求手動(dòng)點(diǎn)擊播放、逐節(jié)觀看視頻,效率較低,對(duì)于工作人士時(shí)間較緊。本文介紹一個(gè)基于 Python + Selenium 的自動(dòng)化腳本,能夠模擬用戶(hù)操作,實(shí)現(xiàn)課程自動(dòng)播放與章節(jié)跳轉(zhuǎn),僅作技術(shù)交流使用,目前所實(shí)現(xiàn)功能僅為單節(jié)課程的刷課,更換課程刷課需要修改Entercourse函數(shù)內(nèi)的Xpath。
- 瀏覽器配置與頁(yè)面訪問(wèn)
腳本使用 Edge 瀏覽器(Chromium 內(nèi)核)作為自動(dòng)化載體,啟動(dòng)瀏覽器后自動(dòng)訪問(wèn)學(xué)習(xí)網(wǎng)站首頁(yè)。在頁(yè)面加載完成后,腳本會(huì)等待一定時(shí)間,確保頁(yè)面元素渲染完成,為后續(xù)操作做好準(zhǔn)備。
- 密碼登錄跳轉(zhuǎn)
平臺(tái)默認(rèn)可能使用掃碼登錄,腳本會(huì)自動(dòng)切換到密碼登錄模式。通過(guò)等待并自動(dòng)點(diǎn)擊相應(yīng)選項(xiàng),腳本能夠順利進(jìn)入用戶(hù)名和密碼輸入界面,從而為自動(dòng)登錄做準(zhǔn)備。
- 自動(dòng)登錄
腳本會(huì)自動(dòng)輸入用戶(hù)的賬號(hào)和密碼,點(diǎn)擊登錄按鈕完成登錄操作。驗(yàn)證碼仍需手動(dòng)拖動(dòng)驗(yàn)證(手動(dòng)驗(yàn)證需要10s內(nèi)完成,否則會(huì)登陸失敗)。登錄成功后,腳本會(huì)等待頁(yè)面跳轉(zhuǎn)完成,確保后續(xù)操作能夠順利進(jìn)行。如果登錄失敗,腳本會(huì)捕獲異常并提示用戶(hù)。
- 查看全部課程與進(jìn)入課程
登錄后,腳本會(huì)點(diǎn)擊“查看全部”按鈕進(jìn)入課程列表頁(yè)面。用戶(hù)可以進(jìn)入指定課程,也可以通過(guò)翻頁(yè)功能訪問(wèn)后續(xù)課程列表,從而實(shí)現(xiàn)全量課程的瀏覽和播放。
- 視頻播放與時(shí)間管理
進(jìn)入課程播放頁(yè)面后,腳本會(huì)自動(dòng)點(diǎn)擊播放按鈕開(kāi)始視頻。通過(guò)解析頁(yè)面顯示的當(dāng)前觀看時(shí)長(zhǎng)和視頻總時(shí)長(zhǎng),腳本能夠?qū)崟r(shí)計(jì)算播放進(jìn)度。總時(shí)間會(huì)被轉(zhuǎn)換為秒數(shù),以便進(jìn)行邏輯判斷,確保視頻播放達(dá)到應(yīng)觀看時(shí)長(zhǎng)。
- 自動(dòng)章節(jié)切換
當(dāng)檢測(cè)到視頻播放完成后,腳本會(huì)自動(dòng)點(diǎn)擊“下一章節(jié)”按鈕進(jìn)入下一節(jié)課程,并繼續(xù)播放。即便在某些情況下未能獲取時(shí)間信息或按鈕不可點(diǎn)擊,腳本也會(huì)嘗試刷新頁(yè)面并重新播放,保證播放流程不中斷。
- 自動(dòng)播放循環(huán)
腳本核心邏輯是循環(huán)監(jiān)測(cè)視頻播放進(jìn)度。如果當(dāng)前章節(jié)未播放完成,腳本會(huì)持續(xù)等待并定期檢查。播放完成后自動(dòng)跳轉(zhuǎn)到下一章節(jié),直至所有課程播放完畢,實(shí)現(xiàn)全程自動(dòng)化。
- 元素安全操作與異常處理
為了提高穩(wěn)定性,腳本封裝了安全的元素點(diǎn)擊和定位函數(shù),并捕獲頁(yè)面刷新或元素失效可能導(dǎo)致的異常。這些機(jī)制確保在不同瀏覽器狀態(tài)下,腳本都能夠順利執(zhí)行。
- 執(zhí)行流程
整個(gè)腳本按照明確流程執(zhí)行:先切換到密碼登錄,再自動(dòng)登錄、查看全部課程、進(jìn)入課程播放頁(yè)面,然后開(kāi)始自動(dòng)播放視頻并循環(huán)切換章節(jié)。該流程保證了從登錄到課程完成的全程自動(dòng)化。
總結(jié)
通過(guò)這個(gè)腳本,實(shí)現(xiàn)了網(wǎng)課自動(dòng)播放、章節(jié)自動(dòng)切換、播放進(jìn)度監(jiān)測(cè)等功能,提供了完整的學(xué)習(xí)自動(dòng)化流程。該項(xiàng)目?jī)H用于技術(shù)交流與 Python 自動(dòng)化練習(xí),實(shí)際使用時(shí)仍需遵守學(xué)校和平臺(tái)的相關(guān)規(guī)定。
代碼如下:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
from selenium.common.exceptions import StaleElementReferenceException
#***********************************開(kāi)發(fā)版:上海應(yīng)用大學(xué)網(wǎng)課自動(dòng)刷視頻***********************************
# 配置 Edge 瀏覽器
edge_options = webdriver.EdgeOptions()
edge_options.use_chromium = True
driver = webdriver.Edge(options=edge_options)
# 訪問(wèn)學(xué)習(xí)網(wǎng)站
driver.get("https://www.learnin.com.cn/#/login")
time.sleep(6) # 等待頁(yè)面加載
# **跳轉(zhuǎn)密碼登錄**
def jumpPasswd():
try:
wait = WebDriverWait(driver, 10)
password_tab = wait.until(EC.element_to_be_clickable(
(By.XPATH, '//*[@id="app"]/div/div/div/div[1]/div[2]/div/div[1]/div[1]/div/label[2]')))
password_tab.click()
print("? 密碼登錄跳轉(zhuǎn)成功")
except Exception as e:
print("? 密碼登錄跳轉(zhuǎn)失敗:", e)
# **自動(dòng)登錄******需要手動(dòng)進(jìn)行拖動(dòng)驗(yàn)證碼驗(yàn)證*************
def login():
try:
username_input = driver.find_element(By.XPATH,
'//*[@id="app"]/div/div/div/div[1]/div[2]/div/div[1]/div[2]/div/form/div[1]/div/div/input')
password_input = driver.find_element(By.XPATH,
'//*[@id="app"]/div/div/div/div[1]/div[2]/div/div[1]/div[2]/div/form/div[2]/div/div[1]/input')
login_button = driver.find_element(By.XPATH,
'//*[@id="app"]/div/div/div/div[1]/div[2]/div/div[1]/div[2]/div/div/div/button')
time.sleep(1)
username_input.send_keys("15346111559") # 用戶(hù)名
password_input.send_keys("Xzl19980216") # 密碼
login_button.click()
time.sleep(3)
print("? 登錄成功")
except Exception as e:
print(f"? 登錄失敗: {e}")
# **查看全部**
def Viewall():
try:
wait = WebDriverWait(driver, 10)
learn_button = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="studentHomeStep4"]/div/div[1]/div/a')))
learn_button.click()
time.sleep(2)
print("? 進(jìn)入查看全部成功")
except Exception as e:
print("? 進(jìn)入查看全部失敗:", e)
# **進(jìn)入課程**
def Entercourse():
try:
wait = WebDriverWait(driver, 10)
learn_button = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="app"]/div/div[2]/div[1]/div[2]/div[1]/div[1]/div[2]/div[2]/a')))
learn_button.click()
time.sleep(2)
print("? 進(jìn)入課程成功")
except Exception as e:
print("? 進(jìn)入課程失敗:", e)
# **翻頁(yè)2**
def Clickpage2():
try:
# driver.switch_to.window(driver.window_handles[-1]) # 打開(kāi)新窗口需要切換到新窗口
wait = WebDriverWait(driver, 10)
learn_button_1 = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="app"]/div/div[2]/div[1]/div[2]/div[2]/div/ul/li[2]')))
learn_button_1.click()
time.sleep(5)
print("? 進(jìn)入翻頁(yè)第2頁(yè)成功")
except Exception as e:
print("? 進(jìn)入翻頁(yè)第2頁(yè)失敗:", e)
# **點(diǎn)擊播放視頻**
def ClicklearnVideo():
try:
driver.switch_to.window(driver.window_handles[-1]) # 切換到新窗口
wait = WebDriverWait(driver, 10)
play_button = wait.until(EC.element_to_be_clickable((By.XPATH,
'//*[@id="app"]/div/div[1]/div[2]/div[1]/div/div[2]/div/div[2]/div/div/div[2]/div/div/div[2]/div/div[1]/div[2]/div[2]/div[1]/button')))
play_button.click()
print("?? 視頻開(kāi)始播放")
time.sleep(2)
except Exception as e:
print("? 播放視頻失敗:", e)
# **將時(shí)間字符串轉(zhuǎn)換為秒數(shù)**
def time_to_seconds(time_str):
try:
h, m, s = map(int, time_str.split(":"))
return h * 3600 + m * 60 + s
except:
return 0 # 如果解析失敗,返回 0 秒
# **點(diǎn)擊下一章節(jié)**
def click_next_chapter(wait):
try:
# 重新定位元素
next_button = wait.until(EC.element_to_be_clickable(
(By.XPATH, '//*[@id="app"]/div/div[1]/div[1]/div[3]/div[3]/button')))
next_button.click()
print("?? 跳轉(zhuǎn)到下一章節(jié)")
time.sleep(5) # 等待新視頻加載
ClicklearnVideo() # 播放新視頻
except Exception as e:
print("? 無(wú)法點(diǎn)擊“下一章節(jié)”:", e)
# **自動(dòng)播放視頻**
def auto_play_videos():
while True:
try:
while True:
wait = WebDriverWait(driver, 10)
time.sleep(10)
# 獲取觀看時(shí)長(zhǎng)和當(dāng)前已觀看時(shí)長(zhǎng)
try:
Btime_elements = wait.until(EC.presence_of_all_elements_located(
(By.XPATH,
'//*[@id="app"]/div/div[1]/div[2]/div[1]/div/div[2]/div/div[2]/div/div/div[3]/div[2]/span[2]')))
# print(f"當(dāng)前時(shí)間{Btime_elements}")
# **如果找不到觀看時(shí)間,直接跳轉(zhuǎn)下一章節(jié)**
if not Btime_elements:
print("?? 未檢測(cè)到觀看時(shí)間,跳轉(zhuǎn)到下一章節(jié)")
click_next_chapter(wait)
continue
Etime_elements = wait.until(EC.presence_of_all_elements_located(
(By.XPATH,
'//*[@id="app"]/div/div[1]/div[2]/div[1]/div/div[2]/div/div[2]/div/div/div[3]/div[2]/span[3]')))
except Exception as e:
# 如果獲取時(shí)間失敗,直接跳到下一章節(jié)
print("?? 未檢測(cè)到已觀看時(shí)間,跳轉(zhuǎn)到下一章節(jié)")
click_next_chapter(wait)
continue
# 獲取文本內(nèi)容
Btime_str = Btime_elements[0].text.strip()
Etime_str = Etime_elements[0].text.strip()
# print(f"當(dāng)前時(shí)間{Btime_str}總時(shí)間{Etime_str}")
# **轉(zhuǎn)換時(shí)間**
Btime_seconds = time_to_seconds(Btime_str) / 0.7
Etime_seconds = time_to_seconds(Etime_str)
print(f"?? 觀看時(shí)長(zhǎng)應(yīng)達(dá)到: {Btime_seconds}秒")
print(f"?? 當(dāng)前已觀看: {Etime_seconds}秒")
# **播放完成,點(diǎn)擊下一章節(jié)**
if Etime_seconds >= Btime_seconds:
print(f"觀看時(shí)長(zhǎng){Etime_seconds}大于總時(shí)長(zhǎng){Btime_seconds}? 視頻播放完成,準(zhǔn)備跳轉(zhuǎn)下一章")
click_next_chapter(wait)
else:
print("?? 正在播放中")
time.sleep(5) # 每 5 秒檢查一次播放進(jìn)度
except Exception as e:
print("? 發(fā)生錯(cuò)誤:", e)
driver.refresh() #發(fā)生錯(cuò)誤刷新頁(yè)面
time.sleep(5) #等待加載
ClicklearnVideo() #重新播放視頻
# 定位元素前先刷新它
def find_element(driver, locator):
return WebDriverWait(driver, 10).until(EC.presence_of_element_located(locator))
# **點(diǎn)擊元素的安全函數(shù)**
def safe_click(xpath):
try:
element = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, xpath)))
element.click()
except StaleElementReferenceException:
# 重新查找并點(diǎn)擊
element = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, xpath)))
element.click()
# **執(zhí)行任務(wù)**
jumpPasswd()
login()
Viewall()
# Clickpage2()
Entercourse()
ClicklearnVideo()
auto_play_videos()

浙公網(wǎng)安備 33010602011771號(hào)