1. 程式人生 > >12306:媽媽再也不用擔心我搶不到票了(1)

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分析

login傳入引數

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上更新(之前程式碼一直放在碼雲上,中文的方便),歡迎大家加入,一起完成,不再為買票而煩惱。

歡迎大家關注微信公眾號:極簡XksA,獲取Python/Java/前端等學習資源!

極簡XksA