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

yizhihongxing

以下是”春节到了教你使用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技术站

(0)
上一篇 2023年5月14日
下一篇 2023年5月14日

相关文章

  • python pandas.DataFrame.loc函数使用详解

    下面是详细讲解”pythonpandas.DataFrame.loc函数使用详解”的完整攻略。 1. 什么是pandas.DataFrame.loc函数 pandas是一个基于NumPy的Python开源数据分析库,提供了高效的数据结构DataFrame。DataFrame是一种二维表格,其中的每一列可以是不同的数据类型(整数、浮点数、字符串等),它类似于电…

    python 2023年5月14日
    00
  • 在Pandas数据框架中把整数转换成字符串的最快方法

    在 Pandas 数据框架中,将整数类型的列转换为字符串类型的列的最快方法是使用 astype() 函数。 具体实现步骤如下: 假设我们有一个名为 df 的数据框架,其中的 column_name 列为整数类型。 使用 astype() 函数将其转换为字符串类型,示例代码如下: python df[‘column_name’] = df[‘column_na…

    python-answer 2023年3月27日
    00
  • Pandas 使用制表符分离器将数据框架转为CSV文件

    导入 Pandas 库 在转换数据框架为 CSV 文件之前需要先导入 Pandas 库,代码如下: import pandas as pd 创建数据框架 为了演示数据框架如何转换为 CSV 文件,我们需要先创建一个实例数据。这里我们创建一个包含学生信息的数据框架,包含姓名、年龄、性别、所属班级、成绩等信息。 # 创建数据框架 df = pd.DataFram…

    python-answer 2023年3月27日
    00
  • pandas数据拼接的实现示例

    下面是关于“pandas数据拼接的实现示例”的完整攻略,包含两个示例说明: 1. 背景介绍 在数据分析过程中,常常会遇到需要将多个数据源的数据拼接和整合成一个完整数据集的情况。pandas是常用的数据分析工具之一,提供了多种数据拼接和整合的方式,本攻略将详细讲解pandas数据拼接的实现。 2. 数据拼接的方式 pandas提供了三种数据拼接方式,分别是co…

    python 2023年5月14日
    00
  • python 如何设置柱状图参数

    下面是关于 Python 中设置柱状图参数的完整攻略: 1. 导入需要的库 在使用任何 Python 库前,我们都需要先导入它们。对于绘制柱状图,我们需要导入 matplotlib 库。 import matplotlib.pyplot as plt 2. 准备数据 在绘制柱状图前,我们需要准备好要绘制的数据。以一个地区的温度为例: region = [‘B…

    python 2023年6月14日
    00
  • pandas读取csv文件提示不存在的解决方法及原因分析

    pandas读取csv文件提示不存在的解决方法及原因分析 在使用pandas读取csv文件时,有时候会出现文件不存在的提示。本篇攻略将为大家详细讲解这一问题的原因和解决方法。 问题原因 当我们使用pandas读取csv文件时,文件路径可能会出现错误,导致文件不存在,因此程序会出现错误提示。以下是几种可能的原因: 文件路径不正确:读取文件时需要正确指定文件的路…

    python 2023年5月14日
    00
  • yolov5 win10 CPU与GPU环境搭建过程

    我来讲解一下 “Yolov5 Win10 CPU与GPU环境搭建过程” 的攻略。 环境要求 首先,我们需要满足以下环境要求: Python >= 3.8 Pytorch >= 1.7.0 CUDA >= 10.2(需要GPU环境) cuDNN >= 8.0.4(需要GPU环境) NVIDIA GPU(需要GPU环境) CPU环境搭建 …

    python 2023年5月14日
    00
  • 用二维列表制作Pandas DataFrame

    二维列表是制作Pandas DataFrame的一种方式,通过将二维列表转换为DataFrame,我们可以在Python中更方便地进行数据分析和处理。下面是用二维列表制作Pandas DataFrame的详细攻略。 准备工作 首先,我们需要导入Pandas库,以便在Python中使用它。导入Pandas的代码如下所示: import pandas as pd…

    python-answer 2023年3月27日
    00
合作推广
合作推广
分享本页
返回顶部