用selenium製作爬蟲爬取教務課程資訊
阿新 • • 發佈:2018-12-12
前段時間在選課,而我們的教務系統又十分蛋疼。先是在選課時不停崩潰,進不去,選課結束要列印選課單時又因為它自己系統太老而不支援64位瀏覽器列印課表。。。沒有辦法我就寫了一個爬取教務課程資訊並將其儲存在MongoDB中的程式,這個程式稍微改改就可以變成搶課指令碼了。內容有:
- 使用selenium驅動chrome瀏覽器
- 用pytesseract識別驗證碼
- MongoDB儲存
首先選課系統長這個樣子:
需要做的是通過指令碼輸入使用者名稱和密碼,並識別驗證碼登陸教務系統,跳轉到選課頁面,獲取選課資訊,最後將資訊儲存於MongoDB中。
開啟開發者工具,定位登陸表單各元素:
依次獲取元素填寫相應欄位,最後模擬點選登陸即可,程式碼如下:
def login(): browser.get('http://gsmis.graduate.buaa.edu.cn/gsmis/main.do') browser.maximize_window() input_id=browser.find_element_by_xpath('//input[@name="id"]') input_password =browser.find_element_by_xpath('//input[@name="password"]') input_checkcode=browser.find_element_by_xpath('//input[@name="checkcode"]') img_checkcode=browser.find_element_by_xpath('//img[@src="/gsmis/Image.do"]') location = img_checkcode.location size = img_checkcode.size browser.save_screenshot('checkcode.png') checkcode=getCheckcode('checkcode.png',location,size) input_id.send_keys(data['id']) input_password.send_keys(data['password']) input_checkcode.send_keys(checkcode) lg_button=browser.find_element_by_xpath('//img[@onclick="document.forms[0].submit()"]') time.sleep(1) lg_button.click()
其中有識別驗證碼的部分,識別函式採取的是將驗證碼截圖,儲存,交給pytesseract識別的方法,為了提高識別準確度,對驗證碼圖片進行了二值化處理,並在OCR識別後對一些容易混淆為字母的數字進行了糾正,程式碼如下:
def initTable(threshold=140): # 二值化函式 table = [] for i in range(256): if i < threshold: table.append(0) else: table.append(1) return table def getCheckcode(savepath,location,size): rep = {'O': '0', # replace list 'I': '1', 'L': '1', 'Z': '2', 'S': '8' }; im = Image.open(savepath) location['x']=825 location['y']=495 left = location['x'] top = location['y'] right = location['x'] + size['width'] bottom = location['y'] + size['height'] im = im.crop((left, top, right, bottom)) im.save(savepath) im = im.convert('L') binaryImage = im.point(initTable(), '1') # binaryImage.show() checkcode = pytesseract.image_to_string(binaryImage, config='-psm 7') for r in rep: checkcode = checkcode.replace(r, rep[r]) print(checkcode) return checkcode
這樣就登陸進入了教務系統主頁,還需要開啟選課頁面。這裡注意frame的切換,在父frame裡無法定位子frame的元素,所以要根據情況switch到子frame:
def navigate():
time.sleep(1)
browser.get("http://gsmis.graduate.buaa.edu.cn/gsmis/toModule.do?prefix=/py&page=/pySelectCourses.do?do=xsXuanKe")
browser.switch_to.frame('frmme')
browser.switch_to.frame('leftFrame')
xuanke=browser.find_element_by_xpath('//a[@href="/gsmis/py/pySelectCourses.do?do=xuanBiXiuKe"]')
xuanke.click()
browser.switch_to.parent_frame()
browser.switch_to.frame('mainFrame')
現在到了這一步,獲取課程資訊並儲存即可:
def prase():
lessons=browser.find_elements_by_class_name("tablefont2")
for lesson in lessons:
infos=lesson.find_elements_by_xpath("./td")
is_selected = infos[0].find_element_by_xpath("./input").is_selected()
if(is_selected):
info={
'when&where':infos[1].text,
'classification': infos[3].text,
'name': infos[4].text,
'teacher': infos[10].text,
'remian': infos[12].text,
}
yield(info)
MONGO_URL = 'localhost'
MONGO_DB = 'jiaowu'
MONGO_COLLECTION = 'Curriculum'
client = pymongo.MongoClient(MONGO_URL)
db = client[MONGO_DB]
def save_to_mongo(result):
"""
儲存至MongoDB
:param result: 結果
"""
try:
if db[MONGO_COLLECTION].insert(result):
print('儲存到MongoDB成功')
except Exception:
print('儲存到MongoDB失敗')
執行結果如下:
完整程式碼:
import pytesseract
import requests
from PIL import Image
import os
from selenium import webdriver
import time
from selenium.webdriver.support.wait import WebDriverWait
import pymongo
data={
'id':'xxxxxxxx',
'password':'xxxxxxxxx',
'checkcode':''
}
browser = webdriver.Chrome()
wait = WebDriverWait(browser, 10)
def initTable(threshold=140): # 二值化函式
table = []
for i in range(256):
if i < threshold:
table.append(0)
else:
table.append(1)
return table
def getCheckcode(savepath,location,size):
rep = {'O': '0', # replace list
'I': '1', 'L': '1',
'Z': '2',
'S': '8'
};
im = Image.open(savepath)
location['x']=825
location['y']=495
left = location['x']
top = location['y']
right = location['x'] + size['width']
bottom = location['y'] + size['height']
im = im.crop((left, top, right, bottom))
im.save(savepath)
im = im.convert('L')
binaryImage = im.point(initTable(), '1')
# binaryImage.show()
checkcode = pytesseract.image_to_string(binaryImage, config='-psm 7')
for r in rep:
checkcode = checkcode.replace(r, rep[r])
print(checkcode)
return checkcode
def login():
browser.get('http://gsmis.graduate.buaa.edu.cn/gsmis/main.do')
browser.maximize_window()
input_id=browser.find_element_by_xpath('//input[@name="id"]')
input_password =browser.find_element_by_xpath('//input[@name="password"]')
input_checkcode=browser.find_element_by_xpath('//input[@name="checkcode"]')
img_checkcode=browser.find_element_by_xpath('//img[@src="/gsmis/Image.do"]')
location = img_checkcode.location
size = img_checkcode.size
browser.save_screenshot('checkcode.png')
checkcode=getCheckcode('checkcode.png',location,size)
input_id.send_keys(data['id'])
input_password.send_keys(data['password'])
input_checkcode.send_keys(checkcode)
lg_button=browser.find_element_by_xpath('//img[@onclick="document.forms[0].submit()"]')
time.sleep(1)
lg_button.click()
def navigate():
time.sleep(1)
browser.get("http://gsmis.graduate.buaa.edu.cn/gsmis/toModule.do?prefix=/py&page=/pySelectCourses.do?do=xsXuanKe")
browser.switch_to.frame('frmme')
browser.switch_to.frame('leftFrame')
xuanke=browser.find_element_by_xpath('//a[@href="/gsmis/py/pySelectCourses.do?do=xuanBiXiuKe"]')
xuanke.click()
browser.switch_to.parent_frame()
browser.switch_to.frame('mainFrame')
def prase():
lessons=browser.find_elements_by_class_name("tablefont2")
for lesson in lessons:
infos=lesson.find_elements_by_xpath("./td")
is_selected = infos[0].find_element_by_xpath("./input").is_selected()
if(is_selected):
info={
'when&where':infos[1].text,
'classification': infos[3].text,
'name': infos[4].text,
'teacher': infos[10].text,
'remian': infos[12].text,
}
yield(info)
MONGO_URL = 'localhost'
MONGO_DB = 'jiaowu'
MONGO_COLLECTION = 'Curriculum'
client = pymongo.MongoClient(MONGO_URL)
db = client[MONGO_DB]
def save_to_mongo(result):
"""
儲存至MongoDB
:param result: 結果
"""
try:
if db[MONGO_COLLECTION].insert(result):
print('儲存到MongoDB成功')
except Exception:
print('儲存到MongoDB失敗')
login()
navigate()
for res in prase():
print(res)
save_to_mongo(res)