最近學校要填寫對於老師的評教,不填寫的就無法進行下周的選課∑^)/
我這么懶,自然不想一個一個點進去填寫,想到最近在學爬蟲,干脆寫一個爬蟲幫我弄算了
╭~~~╮
(o~.~o)
首先打開我們學校的信息門戶:http://my.hfut.edu.cn/(僅限校園網)
可以看到我們學校的北門\(0^◇^0)/
可以看出來,用戶名和密碼還是很好填的,這個驗證碼就很麻煩了......
我選擇的方法是,直接保存屏幕截圖,然后利用定位元素位置定量裁剪圖片,然后利用圖像識別識別圖中驗證碼, 當然,直接選圖片自然是不行,要對圖片先進行處理,這里,我選擇的是對圖像進行灰度處理,並且去除噪點,需要注意的是,很多情況下,驗證碼是錯的,所以需要手動輸入
def convert(im):
#先將圖片進行灰度處理,也就是處理成單色,然后進行下一步單色對比
imgrey = im.convert('L')
#去除圖片噪點,170是經過多次調整后,去除噪點的最佳值
'''
其實就是對已處理的灰度圖片,中被認為可能形成驗證碼字符的像素進行閥值設定,
如果閥值等於170,我就認為是形成驗證碼字符串的所需像素,然后將其添加進一個空table中,
最后通過im.point將使用table拼成一個新驗證碼圖片
'''
threshold = 170
table = []
for i in range(256):
if i < threshold:
table.append(0)
else:
table.append(1)
#使用table(是上面生成好的)生成圖片
out = imgrey.point(table,'1')
out.save( '2222.jpeg','jpeg')
#讀取處理好的圖片的路徑
# a = pic_path + '/' + 'cjb' + str(threshold) + '.jpeg'
img3 = Image.open('2222.jpeg', 'r')
# 將圖片中的像素點識別成字符串(圖片中的像素點如果沒有處理好,
# 可能在識別過程中會有誤差,如多個字符少個字符,或者識別錯誤等)
vcode = pytesseract.image_to_string(img3)
print(vcode) # 此句也是測試結果時使用的
return vcode#此句才是將被破解的驗證碼字符串返回給需要的代碼的
def Verification_code():
browser.save_screenshot('e://aa.png')
imgelement = browser.find_element_by_xpath('//*[@id="captchaImg"]') # 定位驗證碼
location = imgelement.location # 獲取驗證碼x,y軸坐標
size = imgelement.size # 獲取驗證碼的長寬
rangle = (int(location['x'] + 230), int(location['y'] + 70), int(location['x'] + size['width'] + 245),
int(location['y'] + size['height'] + 80)) # 寫成我們需要截取的位置坐標
i = Image.open("e://aa.png") # 打開截圖
frame4 = i.crop(rangle) # 使用Image的crop函數,從截圖中再次截取我們需要的區域
frame4.save('0000.png')
im = Image.open('0000.png').convert('L')
pytesseract.pytesseract.tesseract_cmd = 'C:\/Program Files (x86)\/Tesseract-OCR\/tesseract.exe'
text1 = pytesseract.image_to_string(im)
print(text1)
text1 = pytesseract.image_to_string(im)
print(text1)
text1 = pytesseract.image_to_string(im)
print(text1)
text1 = pytesseract.image_to_string(im)
print(text1)
text1 = pytesseract.image_to_string(im)
print(text1)
text2 = convert(im)
if len(text1) == 4:
if len(text2) == 4:
text = text1
else:
if len(text2) ==4:
text = text2
else: text = text1
return text
def log_in(): browser.get(url) input_user = wait( EC.presence_of_element_located((By.CSS_SELECTOR, '#username')) ) input_pw = wait( EC.presence_of_element_located((By.CSS_SELECTOR, '#password')) ) input_yanzhengma = wait( EC.presence_of_element_located((By.CSS_SELECTOR, '#code')) ) confirm = input('是否使用默認賬戶登錄:') if confirm == 'y': user = '2016214224' pw = 'leiheng.1.1' else: user = input("賬號:") pw = input("密碼:") input_user.send_keys(user) input_pw.send_keys(pw) text = Verification_code() if text: print('驗證碼獲取成功...\n驗證碼為:', text) input_yanzhengma.send_keys(text) else: print('驗證碼獲取失敗') if '0000.png': print('驗證碼保存成功...') text = input('請查看圖片,輸入驗證碼:') input_yanzhengma.send_keys(text) Confirm_login() def Repeat_verification(chance): if not chance: print('驗證碼錯誤,請手動輸入驗證碼...') if '0000.png': print('驗證碼已保存...') text = input('請查看圖片,輸入驗證碼:') input_yanzhengma = wait( EC.presence_of_element_located((By.CSS_SELECTOR, '#code')) ) input_yanzhengma.clear() input_yanzhengma.send_keys(text) Confirm_login() def Confirm_login(): submit = wait( EC.element_to_be_clickable((By.CSS_SELECTOR, '#loginForm > table:nth-child(1) > tbody > tr:nth-child(3) > td > input[type="submit"]:nth-child(3)')) ) submit.click() try: new_button = wait( EC.element_to_be_clickable((By.CSS_SELECTOR, '#pf7802 > div > div.portletContent > table > tbody > tr:nth-child(2) > td:nth-child(1) > table > tbody > tr:nth-child(1) > td > a > img')) ) print('登錄成功...') return 1 except TimeoutException: Repeat_verification(0) return 0
之后,就可以選擇繼續填寫老師的評測了,當然,中間需要跳轉幾個網頁。
def questionnaire(): new_button = wait( EC.element_to_be_clickable((By.CSS_SELECTOR, '#pf7802 > div > div.portletContent > table > tbody > tr:nth-child(2) > td:nth-child(1) > table > tbody > tr:nth-child(1) > td > a > img')) ) new_button.click() windows = browser.window_handles browser.close() browser.switch_to.window(windows[-1]) new_test = wait( EC.element_to_be_clickable((By.CSS_SELECTOR, '#e-op-area > div > div > div > div > div:nth-child(7) > div')) ) new_test.click() windows = browser.window_handles browser.close() browser.switch_to.window(windows[-1]) time.sleep(2) html = browser.page_source partten = re.compile('<a name=.*?url="(.*?)">(.*?)</a>', re.S) items = re.findall(partten, html) for item in items: teacher = item[1] print('正在進行'+teacher+'老師的測評') next_page = 'http://jxglstu.hfut.edu.cn' + item[0] url = next_page browser.get(url) blist = ['達到目標', '匹配', '契合', '認真', '能充分利用教材設計教學方案,並做好教學預設。', '能合理地利用現代教育技術手段。', '能合理地運用多種教學方法。', '能根據教學設計組織教學活動,並對學生進行有效引導 。' , '學生積極參與教學活動,較好地掌握所學知識和技能,並對其發展產生積極影響。', '能根據學生對課堂內容的掌握情況,適當拓展與延伸專業知識,激發學生學習興趣,並拓展學生的學習視野。'] for i in range(10): b = wait( EC.element_to_be_clickable((By.CSS_SELECTOR, '[value="' + blist[i] + '"]')) ) b.click() print(teacher+'老師的評測以結束,進行下一位老師的評測') submit_test = wait( EC.element_to_be_clickable((By.CSS_SELECTOR, '#save-button')) ) time.sleep(2) submit_test.click() time.sleep(1)
到這里基本上已經結束了。
有幾點需要總結:
1)從登陸模塊來看,目前無法解決如何將密碼輸入時進行隱藏,
2)從驗證碼模塊來看,目前圖像識別還是很難
3)從轉跳網頁來看,要注意將操作從先前的窗口轉移到下一個窗口,不然很容易導致查詢網頁元素時找不到而心煩意亂
4)從頁面加載來看,要注意合理選擇頁面加載的標志性元素,保證頁面中需要的元素以及全部加載成功
5)從查找元素來看,要注意對延遲性操作的延遲時間的控制,注意網速,並且合理在BeautifulSoup以及PyQuery和正則表達式中合理選擇。
6)從對元素的操作來看,注意元素的操作方式是否正確
7)從窗口的關閉來說,browser.close()僅僅關閉一個窗口;而browser.quit()關閉的是由這個browser所加載的各個進程,注意結尾使用
8)有一個很尷尬的情況,圖像識別中pytesseract.image_to_string很多時候什么都識別不出來,也不知道出了什么問題