簡單的自動化使用--使用selenium實現學習通網站的刷慕課程序。注釋空格加代碼大概200行不到
相見恨晚啊
github地址
環境Python3.6 + pycharm + chrom瀏覽器 + chromdriver
依賴庫selenium,time,random
- selenium實現自動化控制瀏覽器
- time和random設置隨機的停留時間,使程序更像是人類在控制。
基本思想:使用Python中的selenium庫來控制chrom瀏覽器來刷慕課,而且是模擬人類點擊物理,相當於物理外掛。
1.實現模擬登錄,選擇省份,學校,輸入賬號,密碼,以及驗證碼。
- 使用selenium庫來定義一個chrom實例driver。
- 使用driver來進入登錄網址
- 使用driver的findelementby_xpath方法來選取省份,學校(這個因個人而不同的,程序里面是需要更改的。
1.1點擊選擇單位按鈕,會出現各省份和個學校的列表
1.2.右擊你所在的省份,點擊檢查(這里以河南的洛陽理工為例),右側光標會定位在你所在省份的標簽列,
1.3.右擊標簽-->copy--->copy xpath
1.4.把copy之后的代碼復制到從github下載下來的第十四行代碼中,即
# 點擊河南
henan = driver.find_element_by_xpath('要復制的地方')
henan.click()
1.5.選擇學校,點擊左側列表中的河南,在右側找到你所在的學校,右擊學校點擊檢查
1.6.在右側會光標會顯示在你所在學校的標簽中,右擊--->copy-->copy xpath
1.7把復制的代碼粘貼到從github下載下來的第22行
# 點擊洛陽理工
louyang = driver.find_element_by_xpath('要復制的地方')
louyang.click()
1.8接下來還要修改的代碼部分是你要刷的那個慕課的網址,請確保是下面這個圖中的url鏈接
1.9把整個url復制下來之后要替換的是從github下載下來的代碼中的第45行代碼,把url復制到下面要替換的位置
# 得到慕課網址
get_url = '要替換的地方網址'
driver.get(get_url)
time.sleep(5)
2.接下來就是運行程序,輸入自己的賬號密碼和網頁中的驗證碼。程序就可以跑起來了,就可以實現物理外掛來刷課。
如果只是想使用這個程序的話,上面的就已經夠用了。下載github代碼,修改省份,學校,和慕課網址運行程序就可以開啟物理外掛來刷慕課了。如果想和我一起來維護這個程序的話,可以看下面的講解,進一步了解這一程序的運行原理。
3.接下來就是重點,程序實現的原理。首先獲取一共有多少個章節,遍歷章節,處理網絡不穩定,換公網,點擊播放按鈕,處理答題細節,處理打完題的情況。
3.0 播放器的html代碼是在頁面下面的ifram中的ifram中的hml代碼里面要使用driver的switch_to.frame方法來切換到ifram中去。
- 代碼處理
# 切換到下面的iframe里
try:
driver.switch_to.frame(driver.find_element_by_xpath('//body/div/div/p/div/iframe'))
except:
driver.switch_to.frame(driver.find_element_by_xpath('//body/div/div/p/span/div/iframe'))
3.1找到所有的章節標簽遍歷。
-
所有的章節都在//*[@id="coursetree"]/div里面,使用driver的findelementsby_xpath方法來找到所有標簽,獲取標簽數量,並遍歷
-
-
-
3.1從html代碼中發現每一個大章節的第一個標簽和其他標簽不一樣,第一章節是在//[@id="coursetree"]/div/div中,而下面的章節是在//[@id="coursetree"]/div中比第一章節少了一個div。可以使用try-except語句來處理先獲取點擊第一章節或第二章節的標簽,出現異常再點擊另一個按鈕,這個方法可以完美的處理遍歷章節中使每一個都可以遍歷到
-
下面是章節不一樣的圖
-
下面是處理的代碼
# 點擊章節
try:
driver.find_element_by_xpath('//*[@id="coursetree"]/div[' + str(i + 1) + ']').click()
except:
driver.find_element_by_xpath('//*[@id="coursetree"]/div[' + str(i + 1) + ']/div').click()
3.2點擊播放按鈕,播放按鈕到目前位置發現有兩種一種是直接在視頻框里面的,另一種要先點擊視頻切換到視頻框,在點擊播放按鈕。
- 下面是第一種情況直接就可以點擊播放按鈕
-
- 下面是第二種情況,要先點視頻,再點擊播放按鈕
-
- 下面是處理這兩種情況的處理邏輯
# 找到播放按鈕並點擊
try:
button = driver.find_element_by_xpath('//*[@id="reader"]')
button.click()
except:
driver.find_element_by_xpath('//*[@id="dct2"]').click()
driver.find_element_by_xpath('//*[@id="reader"]').click()
3.3處理網絡問題,有時候使用本校的網是不行的,會出現網絡不佳的問題,所有要使用代碼來直接切換到公網按鈕,使用代碼先點擊本校按鈕,再點擊公網2按鈕(直接點擊公網2按鈕是不行的,實驗過了,這些點擊的按鈕的位置都是通過findelementby_xpath來獲取的,和上面方法一樣不在多說。)
- 下面是實現代碼
# 找到公網
try:
driver.find_element_by_xpath('//*[@id="video"]/div[4]/div[8]/span').click()
driver.find_element_by_xpath('//*[@id="video"]/div[4]/div[8]/div/ul/li[3]/span[1]').click()
except:
pass
3.4像找到快進按鈕啊,靜音按鈕都是一個辦法的。通過findelementby_xpath方法得到並點擊。
4.下面處理答題,完成視頻,和網絡不佳的情況。這些邏輯但是在try-except里面處理的
4.1出現網絡不佳時,使用右擊--->檢查---->右擊copy---->copy xpath來獲取公網2的標簽位置並點擊。
# 當網絡不可用時 點擊公網
try:
driver.find_element_by_xpath('//*[@id="vjserrdisplay-1035"]/ul/li[2]/label').click()
except:
pass
4.2出現答題時找到,視頻中答題位置,找到選擇題選項位置,遍歷每一個選項點擊,總有一個是正確的(而且這個答案是不影響總成績的) -代碼實現
# 找到視頻中出現的答題位置
if driver.find_element_by_xpath('//body/div[4]/div/div[7]/span/div/div'):
# 找到選擇題
button3 = driver.find_elements_by_xpath('//body/div[4]/div/div[7]/span/div/div/ul/li')
# print("button3{}", button3)
while driver.find_element_by_xpath('//body/div[4]/div/div[7]/span/div/div'):
# print(1)
# 對選項進行遍歷
for button1 in button3:
button1 = button1.find_element_by_xpath('label')
# print("button1{}", button1)
button1.click()
time.sleep(random.random() * 3)
# 點擊提交按鈕
button5 = driver.find_element_by_xpath('//body/div[4]/div/div[7]/span/div/div/div[2]')
# print("button5{}", button5)
button5.click()
time.sleep(random.random() * 3)
if driver.switch_to.alert():
al = driver.switch_to.alert()
al.accept()
time.sleep(random.random())
if not driver.find_element_by_xpath('//body/div[4]/div/div[7]/span/div/div'):
# print("答題完成")
break
except Exception as e:
# print("未找到答題位置")
time.sleep(random.random() * 3)
4.3判斷視頻是否看完,找到播放標簽,如果播放標簽的文本是‘重播’那么證明這個視頻已經完成。跳出循環就好。
- 代碼實現
try:
# 找到重播按鈕
rename = driver.find_element_by_xpath('//*[@id="video"]/div[4]/button[1]').get_attribute('title')
if rename == '重播':
break
except Exception as e:
time.sleep(random.random() * 3)
5返回上一層ifram的上一層ifram繼續下一層 循環。
代碼的不足之處:
-暫時不會判斷視頻是否播放過。
- 有一條輸出語句中時間標簽獲取不出來。
- 播放時必須有一台電腦在運行程序,而且鼠標從頁面出去,或者不進入到頁面中,不然會造成暫停異常。(如果你有一台雲主機的話,那就完美了)
運行結果:部分截圖