【Python】模擬登陸上海西南某高校校園網 (jaccount)

很久沒寫東西了,最近學習了一下模擬登陸,以校園網爲例,做一記錄。python

去年的時候寫過一篇模擬登陸的文章,用的是登陸後的cookies,這種操做比較傻瓜,也不智能,不夠自動化,本質仍是手動登陸。
此次我嘗試把登陸過程用python進行,預先提供帳號、密碼便可。web

衆所周知(本校兄弟姐妹),本校全部身份認證現已徹底由jaccount進行,只要經過了這一層驗證,就至關於登陸成功了。
瀏覽器

以登陸校園郵箱爲例,先分析一下登陸流程:

  1. 輸入郵箱網址mail....edu.cn
  2. 跳轉到jaccount驗證頁
  3. 輸入帳號、密碼、驗證碼登陸
  4. 跳轉回郵箱頁面,登陸完成

難點分析:

  1. 跳轉過程當中有哪些數據須要攜帶?
  2. 驗證碼如何獲取?如何識別?

剛開始想用requests解決全部問題,直到試了許屢次也未能成功解決登陸跳轉的問題,只好放棄,轉用更簡單的selenium。selenium是一款可見便可得的自動化測試工具,在爬蟲上用起來十分方便,它經過模擬人實際的操做實現對瀏覽器的控制,好比輸入、點擊、拖動等事件。cookie

依次按照上述流程,進行編碼(完整代碼見文末):dom

步驟1、打開瀏覽器,輸入郵箱網址

browser.get('https://mail.sjtu.edu.cn')

此時,會彈出瀏覽器,自動打開該網頁,固然,也會自動跳轉到jaccount驗證頁面。工具

步驟2、輸入帳號、密碼、驗證碼

帳號、密碼都比較好搞定,本身預設好就好了。而後經過開發者工具定位文本框位置,由如下命令能夠輸入到相應的文本框內。
學習

input_user = browser.find_element_by_id('user')
input_user.send_keys(user)
input_pass = browser.find_element_by_id('pass')
input_pass.send_keys(pswd)

麻煩的仍是驗證碼。首先要找到驗證碼圖片源,再經過OCR工具進行識別。
經過分析,發現驗證碼是由https://jaccount.sjtu.edu.cn/jaccount/captcha這個站點生成的。要獲取到正確的驗證碼,須要傳入相應的uuid參數,以及cookies。OCR工具目前比較好用的是tesseract,所幸咱們這個驗證碼比較簡單,識別率很高。測試

經過對源碼進行搜索,終於找到uuid了,就在這個登陸表單裏,經過xpath獲取一下,拿到value
ui

uuid = browser.find_element_by_xpath('//form/input[@name="uuid"]')
params = {
    'uuid': uuid.get_attribute('value')
}

此處爲了便捷,我使用requests進行驗證碼下載,而selenium的cookies也和requests不一樣,selenium是比較完整的信息,以下:編碼

[{'domain': 'mail.sjtu.edu.cn', 'httpOnly': True, 'name': 'JSESSIONID', 'path': '/', 'secure': False, 'value': '12l9qesot3vw61sz8brl8i74ir'}, {'domain': 'mail.sjtu.edu.cn', 'httpOnly': True, 'name': 'ZM_AUTH_TOKEN', 'path': '/', 'secure': False, 'value': '0_7b1bfd5665cabda2816d04d7e4f8438022c54538_69643d33363a35373935373238652d346539362d346434372d383837332d6331666264356130343337643b6578703d31333a313536393836323130303632323b747970653d363a7a696d6272613b753d313a613b7469643d31303a323134323231343838363b76657273696f6e3d31333a382e382e395f47415f333031393b'}, {'domain': '.sjtu.edu.cn', 'expiry': 1569818955, 'httpOnly': False, 'name': '_gat', 'path': '/', 'secure': False, 'value': '1'}, {'domain': '.sjtu.edu.cn', 'expiry': 1569905295, 'httpOnly': False, 'name': '_gid', 'path': '/', 'secure': False, 'value': 'GA1.3.452166840.1569818896'}, {'domain': '.sjtu.edu.cn', 'expiry': 1632890895, 'httpOnly': False, 'name': '_ga', 'path': '/', 'secure': False, 'value': 'GA1.3.1066557857.1569818896'}]

而咱們傳入requests的只須要cookie名字和值便可,故可經過字典推導式,生成requests所需的cookies:

cookies = browser.get_cookies()
cookies = {i["name"]: i["value"] for i in cookies}

這樣一來就能夠獲取驗證碼了,

response = requests.get(captcha_url, cookies=cookies, params=params)
with open('img.jpeg', 'wb+') as f:
    f.writelines(response)

這樣驗證碼就被保存到img.jpeg文件中,識別驗證碼只須要如下兩行代碼便可:

image = Image.open('img.jpeg')
code = pytesseract.image_to_string(image)

最後,輸入驗證碼,並肯定,就能夠跳轉回登陸後的郵箱界面。

input_code = browser.find_element_by_id('captcha')
input_code.send_keys(code)
input_code.send_keys(Keys.ENTER)

若是你用的是可視化瀏覽器,這時候就能夠看到本身的郵箱了。
能夠再看看當前的url,是否是已經跳轉回郵箱的url了呢?

print(browser.current_url)

成功登陸以後,要爬取什麼東西都很簡單了,好比課程表、好大學在線的課件等等~

完整代碼

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import requests
import pytesseract
from PIL import Image

browser = webdriver.Chrome()

url = "https://mail.sjtu.edu.cn/"
captcha_url = "https://jaccount.sjtu.edu.cn/jaccount/captcha"
user = 'ben'
pswd = '********'


def get_captcha(captcha_url, cookies, params):
    response = requests.get(captcha_url, cookies=cookies, params=params)
    with open('img.jpeg', 'wb+') as f:
        f.writelines(response)

try:
    browser.get(url)
    cookies = browser.get_cookies()
    cookies = {i["name"]: i["value"] for i in cookies}
    uuid = browser.find_element_by_xpath('//form/input[@name="uuid"]')
    params = {
        'uuid': uuid.get_attribute('value')
    }
    get_captcha(captcha_url, cookies, params)
    image = Image.open('img.jpeg')
    code = pytesseract.image_to_string(image)
    print(code)
    input_user = browser.find_element_by_id('user')
    input_user.send_keys(user)
    input_pass = browser.find_element_by_id('pass')
    input_pass.send_keys(pswd)
    input_code = browser.find_element_by_id('captcha')
    input_code.send_keys(code)
    input_code.send_keys(Keys.ENTER)
    print(browser.current_url)
finally:
    print('success!')
相關文章
相關標籤/搜索