12306:媽媽再也不用擔心我搶不到票了(1)
一、寫在前面
正值國慶之際,我還在為搶不到火車票,只能坐大巴回家而煩惱~你呢?
好訊息來了,從學完這篇推文後,你就再也不用每天求這個朋友圈,求那個qq空間了。
第一篇,我們先登入12306,讀完本篇,你將學會:如何模擬登入,基本圖片驗證方法,一波三折,過程很有意思,參考了網上一些資料。
二、一頓騷操作
流程(字有點醜,馬馬虎虎看吧 ):
1.登入圖片驗證破解
(1)獲取登入頁面,session 儲存 cookies值。
訪問頁面:https://kyfw.12306.cn/otn/login/init
,F12頁面分析,如下:
Headers中
Request URL:https://kyfw.12306.cn/otn/login/init
Request Method: GET
- 程式碼:
import requests
import os
from fake_useragent import UserAgent
# 1.獲取登入
# 請求頭,反爬偽裝
headers = {
"User-Agent": UserAgent(verify_ssl=False).random,
"Host":"kyfw.12306.cn",
"Referer":"https://kyfw.12306.cn/otn/passport?redirect=/otn/"
}
login_url = 'https://kyfw.12306.cn/otn/login/init'
# 1.1 cookie保持
session = requests.Session()
# 1.2 get請求
login_response = session.get(login_url,headers = headers)
login_html = login_response.text
# print(login_html)
(2)獲取驗證圖片,破解驗證操作
- 破解思路:
從頁面上下載驗證圖片到本地,然後按要求選擇正確圖片位置,傳遞正確圖片座標,模擬頁面點選,傳送請求,模擬驗證操作。 - 驗證圖片頁面分析:
Headers中
Request URL: https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&0.8854830207575652
Request Method: GET
- 檢查驗證分析:
這個必須在頁面上進行賬戶密碼輸入,驗證選擇後才能加載出來,所以我就輸入賬號和錯誤密碼,圖片驗證,加載出下面結果:
captcha-check :用於檢查驗證圖片是否選擇正確(驗證正確)
login : 使用者登入賬號、密碼判斷
都是POST請求
Headers中
Request URL: https://kyfw.12306.cn/passport/captcha/captcha-check
Request Method: POST
data = {
“answer”: positions,
“login_site”: “E”,
“rand”: “sjrand”
}
- 程式碼:
# 2.獲取並破解驗證操作
# 2.1 下載驗證圖片
captcha_url = 'https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&0.8854830207575652'
captcha_response = session.get(captcha_url,headers = headers)
# 檔案儲存路徑
image_path = os.path.abspath('image') + '/captcha_image.jpg'
# 以二進位制寫入檔案
with open(image_path,'wb') as image_file:
image_file.write(captcha_response.content)
# 2.2 驗證
check_url = 'https://kyfw.12306.cn/passport/captcha/captcha-check'
# 輸入資料格式為:x1,y1,x2,y2,...,xn,yn
positions = input("請輸入驗證碼: ") # 正確圖片座標
# 傳送驗證碼
data = {
"answer": positions,
"login_site": "E",
"rand": "sjrand"
}
check_response = session.post(check_url,data = data,headers = headers)
check_result = check_response.json()
# 測試發現,result_code = 4 時,表示驗證成功
if not check_result['result_code'] == 4:
exit("驗證失敗")
print(check_result )
- 執行結果:
2.登入
(1)登入 login 分析
- F12分析
Request URL: https://kyfw.12306.cn/passport/web/login
Request Method: POST
data = {
‘username’: Account_number, # 使用者賬號
‘password’: Password, # 使用者密碼
‘appid’: ‘otn’
}
- 程式碼:
# 3.開始登入操作
login_check_url = 'https://kyfw.12306.cn/passport/web/login'
login_check_data = {
'username': Account_number,
'password': Password,
'appid': 'otn'
}
login_check_response = session.post(login_check_url,data=login_check_data,headers = headers)
print(login_check_response.json())
- 執行結果:
然而並沒有正真的登入成功。
(1)登入 許可權獲取
- 基本分析
成功登入12306後頁面為圖示:
可以查詢我們爬取的頁面原始碼中包不包含我的名字來判斷:我們是否是真的登入成功了,12306的內部許可權驗證比較麻煩,從最開始的圖解可以看出來,掩飾過驗證,密碼賬號輸入之外,還有許可權設定,還是兩層,程式碼如下,不理解就加我微信:zs820553471吧。
- 程式碼
# 4. 獲取許可權 authority
# 4.1 獲取許可權金鑰:newapptk
uamtk_data = {
"appid":"otn"
}
uamtk_url = "https://kyfw.12306.cn/passport/web/auth/uamtk"
uamtk_response = session.post(uamtk_url, headers=headers, data=uamtk_data)
uamtk_dict = uamtk_response.json()
newapptk = uamtk_dict['newapptk']
# print(uamtk_dict['newapptk'])
# 4.2 傳遞金鑰,獲取許可權
uamauthclient_data = {
"tk" : newapptk
}
uamauthclient_url = "https://kyfw.12306.cn/otn/uamauthclient"
uamauthclient_response = session.post(uamauthclient_url, headers=headers, data=uamauthclient_data)
# 5 正真的登入
initMy_url = "https://kyfw.12306.cn/otn/index/initMy12306"
initMy_response = session.get(initMy_url, headers=headers)
my_name = initMy_response.text.find("張建華")
if not my_name == -1:
print("使用者已經登入成功")
- 執行結果
三、隨便說說
剛開始寫這篇推文的時候本來是想一篇寫完12306登入,車次資訊獲取,搶票,購票操作的,可寫著寫著,發現事情不是這麼簡單,心有餘而力不足,昨天在GitHub上開了個賬戶,12306系列也會在GitHub上更新(之前程式碼一直放在碼雲上,中文的方便),歡迎大家加入,一起完成,不再為買票而煩惱。