登录流程

-1访问登录页面
url = https://kyfw.12306.cn/otn/login/init
method = get
-2下载验证码(是图片,它一定会依赖cookie)
url = https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&0.20111433490049846
method = get
-3校验验证码
url = https://kyfw.12306.cn/passport/captcha/captcha-check
method = post
formdata:
answer: 249,50,112,115 (坐标点,像数坐标)
login_site: E
rand: sjrand
-4校验用户名和密码
url = https://kyfw.12306.cn/passport/web/login
method = post
formdata:
username: wcfdehao
password: 123456
appid: otn
订单流程
1.提交订单
url = https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest
mehod = post
form data *** secretStr 是列车信息 url解码形式
secretStr: btLfw+HTibWiHnSEmTvw5yvacWFhpxns3wcx91HHzxea/TNtLgD+6kifAX6C2FUKdytfa1ZK33KT
jxvur7fpZncRICP7CZT4FtTOZKwupeHGH7BAI/VrL91fwsAuiaDKK/2DNqtzKN0EBKUpYarlb8bl
GO0l/ylWYuWL1Xi4TJMt4e34jAEnJuVvhGH6lrvCz62keu3k3mbbT/KfRGPO8LUY3nzgFQeH4Kkk
ELQPj78Ou/ftUNJFYQRAVczRpVDOClhBoA==
train_date: 2018-07-01
back_train_date: 2018-06-28
tour_flag: dc
purpose_codes: ADULT
query_from_station_name: 北京
query_to_station_name: 上海
undefined:
2.获取选票页面(获取参数)
url= 'https://kyfw.12306.cn/otn/confirmPassenger/initDc'
method = post
formdata
_json_att:
获取参数var globalRepeatSubmitToken = 'a33f8ffafca89882f3a0d0b8d6d6f263';
3.获取乘客信息
url=https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs
method=post
formdata
_json_att:
REPEAT_SUBMIT_TOKEN: a33f8ffafca89882f3a0d0b8d6d6f263
4.检查订单信息
url = https://kyfw.12306.cn/otn/confirmPassenger/checkOrderInfo
method= post
formdata
cancel_flag: 2
bed_level_order_num: 000000000000000000000000000000
passengerTicketStr: 3,0,1,肖飞,1,430623198312027266,15873061798,N
oldPassengerStr: 肖飞,1,430623198312027266,1_
tour_flag: dc
randCode:
whatsSelect: 1
_json_att:
REPEAT_SUBMIT_TOKEN: a33f8ffafca89882f3a0d0b8d6d6f263
通过js ajax 请求 分析参数的构成
passengerTicketStr: 座位类型,0,票类型(成人票/儿童票),姓名,身份类型,身份证号码,电话号码,保存状态
{"validateMessagesShowId":"_validatorMessage","status":true,"httpstatus":200,"data":{"ifShowPassCode":"N","canChooseBeds":"N","canChooseSeats":"N","choose_Seats":"MOP9","isCanChooseMid":"N","ifShowPassCodeTime":"1","submitStatus":true,"smokeStr":""},"messages":[],"validateMessages":{}}
5.提交订单队列
url ='https://kyfw.12306.cn/otn/confirmPassenger/getQueueCount'
mehtod=post
formdata:
train_date: Mon Jul 02 2018 00:00:00 GMT+0800 (中国标准时间)
train_no: 670000K4370C
stationTrainCode: K436
seatType: 3
fromStationTelecode: MLQ
toStationTelecode: WCN
leftTicket: DaH%2FPK14JyJ3Bt8Z8DUci8jxWAtIvpXQO%2FFY%2F33cfybr80tl
purpose_codes: 00
train_location: Q6
_json_att:
REPEAT_SUBMIT_TOKEN: a33f8ffafca89882f3a0d0b8d6d6f263
通过js ajax 请求 分析参数的构成
Python爬虫源代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Time : 2018/6/25 0025 19:27
import requests
import random
import config
from station import station
class TicketRob:
def __init__(self):
self.session = requests.Session()
self.session.headers.update({
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
})
self.index_url = 'https://kyfw.12306.cn/otn/login/init'
self.captcha_url = 'https://kyfw.12306.cn/passport/captcha/captcha-image'
self.login_url = 'https://kyfw.12306.cn/passport/web/login'
self.check_captcha_url = 'https://kyfw.12306.cn/passport/captcha/captcha-check'
self.uamtk_url = 'https://kyfw.12306.cn/passport/web/auth/uamtk'
self.auth_url = 'https://kyfw.12306.cn/otn/uamauthclient'
self.left_tickets_url = 'https://kyfw.12306.cn/otn/leftTicket/query'
self.submit_order_url = 'https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest'
self.point = {
'1': '35,43',
'2': '108,43',
'3': '185,43',
'4': '254,43',
'5': '34,117',
'6': '108,117',
'7': '180,117',
'8': '258,117',
}
def get_point(self, nums):
"""
拼接坐标点
:param nums: 图片序号 '1,2'
:return:
"""
nums = nums.split(',')
temp = []
for item in nums: # ['1', '2']
temp.append(self.point[item])
return ','.join(temp)
# 检查用户名密码
def login(self, username, password):
data = {
'username': username,
'password': password,
'appid': 'otn'
}
self.session.get(self.index_url) # 1
self.get_captcha() # 2
check_res = self.check_captcha() # 3
if check_res:
response = self.session.post(self.login_url, data=data) # 4
print(response.text)
if response.json()['result_code'] == 0:
tk = self.get_tk() # 5
auth_res = self.get_auth(tk) # 6
if auth_res:
return {'status': True, 'info': '登陆成功'}
else:
return {'status': False, 'info': '权限获取失败!'}
else:
return {'status': False, 'info': '用户名密码错误'}
else:
return {'status': False, 'info': '验证码校验失败!'}
# 校验验证码
def check_captcha(self):
data = {
'answer': self.get_point(input('请输入正确的图片序号>>>:')),
'login_site': 'E',
'rand': 'sjrand'
}
response = self.session.post(self.check_captcha_url, data=data)
if response.json()['result_code'] == '4':
return True
return False
# 获取验证码
def get_captcha(self):
data = {
'login_site': 'E',
'module': 'login',
'rand': 'sjrand',
str(random.random()): ''
}
response = self.session.get(self.captcha_url, params=data)
with open('captcha.jpg', 'wb') as f:
f.write(response.content)
# 获取权限token
def get_tk(self):
uamtk_data = {
'appid': 'otn'
}
response = self.session.post(self.uamtk_url, data=uamtk_data)
return response.json()['newapptk']
# 获取权限
def get_auth(self, tk):
auth_data = {
'tk': tk
}
response = self.session.post(self.auth_url, data=auth_data)
if response.json()['result_code'] == 0:
return True
return False
# 查余票
def query_left_ticket(self, train_date, from_station, to_station):
# data = { ***** 参数的顺序非常重要
# 'leftTicketDTO.train_date': train_date, # '2018-06-30', # 是时间
# 'leftTicketDTO.from_station': from_station, # 'BJP', # 起始站
# 'leftTicketDTO.to_station': to_station, # 'SHH', # 到达站
# 'purpose_codes': 'ADULT'
# }
url = '%s?leftTicketDTO.train_date=%s&leftTicketDTO.from_station=%s&leftTicketDTO.to_station=%s&purpose_codes=ADULT' % (
self.left_tickets_url,train_date,from_station,to_station)
response = self.session.get(url)
res = response.json()
if res['status']:
return res['data']['result']
# 提交订单
def submit_order(self, secretstr):
data = {
'secretStr':secretstr,
'train_date': '2018-07-01',
'back_train_date': '2018-06-28',
'tour_flag': 'dc',
'purpose_codes': 'ADULT',
'query_from_station_name': '北京',
'query_to_station_name': '上海',
'undefined':''
}
response = self.session.post(self.submit_order_url, data=data)
print(response.text)
# {"validateMessagesShowId":"_validatorMessage","status":true,"httpstatus":200,"data":"N","messages":[],"validateMessages":{}}
if __name__ == '__main__':
from urllib import parse
ticket = TicketRob()
ticket.login(config.username, config.password) # 登陆
res = ticket.query_left_ticket('2018-07-01', station['北京'][2], station['上海'][2]) # 查票
print(res)
print('111111111111111111111')
secretstr = res[2].split('|')[0]
secretstr = parse.unquote(secretstr)
print(secretstr)
print('22222222222222222222')
ticket.submit_order(secretstr)
# res = ticket.query_left_ticket('2018-06-30', 'BJP', 'SHH')
# print(res)
# print(ticket.login(config.username, config.password))
# temp = {
# 'a': {
# 'b': 'aaa'
# }
# }
网友评论