以下是”春节到了教你使用python来抢票回家“的完整攻略:
1. 前置条件
在使用 Python 进行自动购票之前,你需要满足以下条件:
- 一台能够访问网络的计算机。
- 已经安装 Python,并了解 Python 的基础语法和操作。
- 了解如何解析 HTML 和发送网络请求。
- 已经获取了想要购买的车票的 url、出发站和目的站代码,以及出发时间、车次等信息。
2. 需要掌握的Python库
- requests: 用于发送网络请求,获取响应内容。
- BeautifulSoup: 用于解析 HTML 文件,提取所需要的信息。
- execjs: 用于执行 Javascript 代码。
- time: 用于进行时间控制。
可以在命令行中使用以下命令进行安装:
pip install requests BeautifulSoup4 PyExecJS
3. 代码实现
以下是一份简单的 Python 代码来模拟登录并购买车票的过程。
3.1 模拟登录
import requests
from bs4 import BeautifulSoup
import execjs
# 示例参数,请替换为自己的值
username = 'your_username'
password = 'your_password'
login_url = 'https://kyfw.12306.cn/passport/web/login'
# 获取cookie
session = requests.session()
res = session.get(login_url)
cookie = requests.utils.dict_from_cookiejar(session.cookies)
# 解析html,获取一些必要的参数lt、execution,以及密码加密用的公钥
soup = BeautifulSoup(res.text, 'html.parser')
lt = soup.find('input', {'name': 'lt'})['value']
exec_code = soup.find('script', {'minfraud-honeypot': 'javascript'})['src']
res2 = session.get(exec_code)
pub_key = execjs.compile(res2.text).call("getKey")
en_password = execjs.compile(res2.text).call("getPwd", pub_key, password)
# 发送post请求,模拟登录
data = {
'username': username,
'password': en_password,
'lt': lt,
'execution': 'e1s1',
'_eventID': 'submit',
'submit': '',
}
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.36',
'Referer': 'https://kyfw.12306.cn/otn/resources/login.html'
}
response = session.post(login_url, data=data, headers=headers)
3.2 查询车票信息
# 示例参数,请替换为自己的值
from_station = 'BJP'
to_station = 'SHH'
start_time = '2019-01-01'
query_url = "https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=" + start_time + "&leftTicketDTO.from_station=" + from_station + "&leftTicketDTO.to_station=" + to_station + "&purpose_codes=ADULT"
# 发送查询请求,获取可购买车票信息
query_res = session.get(query_url)
# 解析json,获取所有车次的信息
trains = query_res.json()['data']['result']
3.3 执行购票操作
# 示例参数,请替换为自己的值
train_num = 'G1'
seat_type = '二等座'
# 构造购票url及请求体
buy_url = ("https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest?"
"secretStr={0}&train_date={1}&"
"back_train_date={2}&tour_flag=dc&"
"purpose_codes=ADULT&query_from_station_name={3}&"
"query_to_station_name={4}&undefined=").format(secret_str, start_time, start_time, from_station_name, to_station_name)
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.36',
'Referer': 'https://kyfw.12306.cn/otn/leftTicket/init'
}
data = {
'secretStr': secret_str,
'train_date': start_time,
'back_train_date': start_time,
'tour_flag': 'dc',
'purpose_codes': 'ADULT',
'query_from_station_name': from_station_name,
'query_to_station_name': to_station_name,
'undefined': ''
}
# 发送post请求,进入购票页面
response = session.post(buy_url, headers=headers, data=data)
# 检查购票页面是否正确返回
if response.status_code != 200:
print("进入购票页面失败!")
exit()
# 获取购票页面的submit_token
soup = BeautifulSoup(response.text, 'html.parser')
submit_token = soup.select_one('input[name="globalRepeatSubmitToken"]')['value']
# 构造订单确认url及请求体
order_confirm_url = "https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest"
params = {
'tour_flag': 'dc',
'is_org_price': 'N',
'round_train_date': start_time,
'train_date': start_time,
'back_train_date': start_time,
'from_station_name': from_station_name,
'to_station_name': to_station_name,
'purpose_codes': 'ADULT',
'train_location': secret_str.split('#')[1],
'_json_att': '',
'REPEAT_SUBMIT_TOKEN': submit_token
}
data = {
'passengerTicketStr': '{0},0,1,{1},N'.format(seat_type_code, passenger_seed),
'oldPassengerStr': '{0},{1},1_'.format(passenger_name, id_num),
'randCode': '',
'whatsSelect': '1',
'_json_att': '',
'REPEAT_SUBMIT_TOKEN': submit_token
}
# 发送post请求,进行订单确认
response = session.post(order_confirm_url, headers=headers, params=params, data=data)
# 检查订单确认页面是否正确返回
if response.status_code != 200:
print("订单确认失败!")
exit()
4. 示例说明
以下是一些有关代码实现的示例说明:
4.1 爬取车票信息
代码中需要构造查询url,并根据返回结果解析车票信息。示例中查询了车次从"BJP"(北京站)到"SHH"(上海站)的所有列车,并输出了经过这两个站点的车次号和出发、到达时间:
from_station = 'BJP'
to_station = 'SHH'
start_time = '2019-01-01'
query_url = "https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=" + start_time + "&leftTicketDTO.from_station=" + from_station + "&leftTicketDTO.to_station=" + to_station + "&purpose_codes=ADULT"
# 发送查询请求,获取可购买车票信息
query_res = session.get(query_url)
# 解析json,获取所有车次的信息
trains = query_res.json()['data']['result']
# 输出所有经过这两个站点的车次号和出发、到达时间
for train in trains:
data_list = train.split('|')
train_num = data_list[3]
start_time = data_list[8]
arrive_time = data_list[9]
if '北京' in data_list[6] and '上海' in data_list[7]:
print('{0}: {1} -> {2}'.format(train_num, start_time, arrive_time))
4.2 购票操作
代码中需要构造购票url和订单确认url,并根据返回结果检查流程是否正确进行,最后成功提交购票订单。示例中为购买G1列车的二等座车票:
# 示例参数,请替换为自己的值
train_num = 'G1'
seat_type = '二等座'
# 构造购票url及请求体
buy_url = ("https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest?"
"secretStr={0}&train_date={1}&"
"back_train_date={2}&tour_flag=dc&"
"purpose_codes=ADULT&query_from_station_name={3}&"
"query_to_station_name={4}&undefined=").format(secret_str, start_time, start_time, from_station_name, to_station_name)
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.36',
'Referer': 'https://kyfw.12306.cn/otn/leftTicket/init'
}
data = {
'secretStr': secret_str,
'train_date': start_time,
'back_train_date': start_time,
'tour_flag': 'dc',
'purpose_codes': 'ADULT',
'query_from_station_name': from_station_name,
'query_to_station_name': to_station_name,
'undefined': ''
}
# 发送post请求,进入购票页面
response = session.post(buy_url, headers=headers, data=data)
# 检查购票页面是否正确返回
if response.status_code != 200:
print("进入购票页面失败!")
exit()
# 获取购票页面的submit_token
soup = BeautifulSoup(response.text, 'html.parser')
submit_token = soup.select_one('input[name="globalRepeatSubmitToken"]')['value']
# 构造订单确认url及请求体
order_confirm_url = "https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest"
params = {
'tour_flag': 'dc',
'is_org_price': 'N',
'round_train_date': start_time,
'train_date': start_time,
'back_train_date': start_time,
'from_station_name': from_station_name,
'to_station_name': to_station_name,
'purpose_codes': 'ADULT',
'train_location': secret_str.split('#')[1],
'_json_att': '',
'REPEAT_SUBMIT_TOKEN': submit_token
}
data = {
'passengerTicketStr': '{0},0,1,{1},N'.format(seat_type_code, passenger_seed),
'oldPassengerStr': '{0},{1},1_'.format(passenger_name, id_num),
'randCode': '',
'whatsSelect': '1',
'_json_att': '',
'REPEAT_SUBMIT_TOKEN': submit_token
}
# 发送post请求,进行订单确认
response = session.post(order_confirm_url, headers=headers, params=params, data=data)
# 检查订单确认页面是否正确返回
if response.status_code != 200:
print("订单确认失败!")
exit()
# 获取订单排队等待时间
json_res = response.json()
wait_time = json_res['data']['waitTime']
if 'orderId' not in json_res['data']:
print("购票失败!原因:{0}".format(json_res['data']['errMsg']))
exit()
# 构造提交订单url及请求体
submit_order_url = "https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueue"
data = {
'passengerTicketStr': '{0},0,1,{1},N'.format(seat_type_code, passenger_seed),
'oldPassengerStr': '{0},{1},1_'.format(passenger_name, id_num),
'randCode': '',
'purpose_codes': '00',
'key_check_isChange': json_res['data']['checkCodeKey'],
'leftTicketStr': json_res['data']['leftTicketStr'],
'train_location': json_res['data']['train_location'],
'choose_seats': '',
'seatDetailType': '000',
'whatsSelect': '1',
'roomType': '00',
'dwAll': 'N',
'_json_att': '',
'REPEAT_SUBMIT_TOKEN': submit_token
}
# 进行购票
while True:
response = session.post(submit_order_url, headers=headers, data=data)
# 检查购票提交返回值
if response.status_code != 200:
print("提交订单失败!")
continue
# 获取提交订单json
json_res = response.json()
if 'data' in json_res and json_res['data']['submitStatus']:
print("购票成功!")
break
else:
print("购票失败!{0}".format(json_res['messages'][0]))
以上是示例代码实现,实践中还需要了解如何模拟验证码、如何队列表单优化等更多问题。因此在使用 python 刷票时也需要根据需求逐步完善代码,针对不同的问题采用不同的方式进行解决。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:春节到了 教你使用python来抢票回家 - Python技术站