春节到了 教你使用python来抢票回家

使用Python抢票回家

春节是中国人最重要的传统节日之一,也是全球最大规模的人口迁徙之一。对于不能提前预订车票来回家的人来说,抢票是他们最紧迫的任务之一。利用Python,您可以写一个简单但有效的脚本来帮助您抢票回家。

准备工作

在编写抢票脚本之前,您需要准备以下内容:

一个12306账户

一个能够发送http请求的Python库,例如requests

一个用于解析HTML的Python库,例如beautifulsoup4

一个支持图像识别的Python库,例如pytesseract和pillow

登录12306

登录12306是使用Python抢票的第一步。在这里,我们将使用requests库发送POST请求来登录12306:

import requests

session = requests.session()

login_url = 'https://kyfw.12306.cn/otn/login/init'

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}

username = 'your_username'

password = 'your_password'

# 发送GET请求,获取cookie信息

response = session.get(login_url, headers=headers)

soup = BeautifulSoup(response.content, 'html.parser')

login_form = soup.find('form', id='loginForm')

login_url = login_form['action']

login_random_code = login_form['data-loginrand']

# 发送POST请求,进行登录

data = {

'username': username,

'password': password,

'appid': 'otn',

'randomCode': '',

'isAutoSug': 'N',

'loginRand': login_random_code

}

login_headers = headers.copy()

login_headers.update({'Referer': 'https://kyfw.12306.cn/otn/login/init'})

response = session.post(login_url, data=data, headers=login_headers)

在以上代码中,我们使用了requests库的session功能来保持会话状态,并且在发送POST请求时添加必要的头部信息。注意,我们需要通过GET请求来获取cookie信息、登录URL和随机码等必要信息。

查询余票

查询余票是抢票的核心步骤之一。以下是查询余票的代码:

query_url = 'https://kyfw.12306.cn/otn/leftTicket/queryZ'

def query_ticket(start_station, end_station, date):

params = {

'leftTicketDTO.train_date': date,

'leftTicketDTO.from_station': start_station,

'leftTicketDTO.to_station': end_station,

'purpose_codes': 'ADULT'

}

response = session.get(query_url, params=params, headers=headers, verify=False)

data = response.json()

ticket_list = data['data']['result']

for ticket_info in ticket_list:

ticket_info = ticket_info.split('|')

if ticket_info[0] != '':

# 以下是您需要关注的列车信息

train_no = ticket_info[3] # 车次

from_station_name = ticket_info[6] # 出发站

to_station_name = ticket_info[7] # 到达站

start_time = ticket_info[8] # 出发时间

arrival_time = ticket_info[9] # 到达时间

duration = ticket_info[10] # 历时

swz_num = ticket_info[32] or '--' # 商务座/特等座

tz_num = ticket_info[25] or '--' # 特等座/商务座

zy_num = ticket_info[31] or '--' # 一等座

ze_num = ticket_info[30] or '--' # 二等座

gr_num = ticket_info[21] or '--' # 高级软卧

rw_num = ticket_info[23] or '--' # 软卧

dw_num = ticket_info[27] or '--' # 动卧

yw_num = ticket_info[28] or '--' # 硬卧

rz_num = ticket_info[24] or '--' # 软座

yz_num = ticket_info[29] or '--' # 硬座

wz_num = ticket_info[26] or '--' # 无座

首先,我们需要确定查询余票的URL,默认是queryZ。在查询余票的请求中,我们需要指定出发日期、出发站和到达站等信息。发送请求后,我们需要对返回结果进行解析,以获取需要的信息。在以上代码中,我们只获取了每趟列车的车次、出发站、到达站、出发时间、到达时间和票量等信息。

选择座位

为了抢到票,我们还需要选择我们需要的座位类型。以下是选择座位的代码:

def submit_order(train_no, from_station_name, to_station_name, start_time, date):

submit_url = 'https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest'

data = {

'secretStr': '',

'train_date': date,

'back_train_date': '',

'tour_flag': 'dc',

'purpose_codes': 'ADULT',

'query_from_station_name': from_station_name,

'query_to_station_name': to_station_name,

'undefined': ''

}

response = session.post(submit_url, data=data, headers=headers, verify=False)

if response.status_code == 200:

initdc_url = 'https://kyfw.12306.cn/otn/confirmPassenger/initDc'

data = {

'_json_att': ''

}

response = session.post(initdc_url, data=data, headers=headers, verify=False)

if response.status_code == 200:

# 进行图像识别

img_url = 'https://kyfw.12306.cn/otn/passcodeNew/getPassCodeNew?module=passenger&rand=randp&0.6034260117320401'

response = session.get(img_url, headers=headers, verify=False)

with open('code.png', 'wb') as f:

f.write(response.content)

img = Image.open('code.png')

code = pytesseract.image_to_string(img)

code = code.strip()

print(code)

在以上代码中,我们首先发送一个submitOrderRequest请求来获取secretStr等必要信息。然后,我们又发送了一个get请求,来获取用于显示验证码的图片,并使用pytesseract进行图像识别。等到我们成功填写了验证码之后,我们就可以提交订单了。

提交订单

以下是提交订单的代码:

def check_order_info():

checkorder_url = 'https://kyfw.12306.cn/otn/confirmPassenger/checkOrderInfo'

data = {

'cancel_flag': '2',

'bed_level_order_num': '000000000000000000000000000000',

'passengerTicketStr': '',

'oldPassengerStr': '',

'tour_flag': 'dc',

'randCode': code,

'whatsSelect': '1',

'_json_att': '',

'REPEAT_SUBMIT_TOKEN': ''

}

response = session.post(checkorder_url, data=data, headers=headers, verify=False)

print(response.content)

def confirm_order():

confirm_url = 'https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueue'

data = {

'passengerTicketStr': '',

'oldPassengerStr': '',

'randCode': code,

'purpose_codes': 'ADULT',

'key_check_isChange': 'B0E67E1FEDB9DC2A74AA7B69771BB08024BBD37E704AE84DCB067D5D',

'leftTicketStr': '',

'train_location': '',

'choose_seats': '',

'seatDetailType': '000',

'whatsSelect': '1',

'roomType': '00',

'dwAll': 'N',

'_json_att': '',

'REPEAT_SUBMIT_TOKEN': ''

}

response = session.post(confirm_url, data=data, headers=headers, verify=False)

print(response.content)

def get_queue_count(train_no, from_station_name, to_station_name, start_time, seat_type, date):

getqueuecount_url = 'https://kyfw.12306.cn/otn/confirmPassenger/getQueueCount'

data = {

'train_date': date,

'train_no': train_no,

'stationTrainCode': 'G1234', # 从查询余票的结果中获取

'seatType': seat_type,

'fromStationTelecode': 'VNP', # 从查询余票的结果中获取

'toStationTelecode': 'NJH', # 从查询余票的结果中获取

'leftTicket': '',

'purpose_codes': '00',

'train_location': 'P2',

'_json_att': '',

'REPEAT_SUBMIT_TOKEN': ''

}

response = session.post(getqueuecount_url, data=data, headers=headers, verify=False)

print(response.content)

check_order_info()

confirm_order()

get_queue_count(train_no, from_station_name, to_station_name, start_time, seat_type, date)

最后,我们需要完成订单的确认和队列数量的查询。在以上代码中,我们首先检查并确认订单信息,然后提交订单,最后,我们获取队列数量以进一步确认是否有座位。

总结

使用Python抢票可能需要一些前期准备和学习,但一旦您了解了基本原理和如何使用Python进行自动化脚本编写,您将更容易地抢到票。

后端开发标签