抢票系统是一个复杂的程序,需要涉及到网站登录、查询、购票等多个过程。以下是一个简单的抢票程序,仅供参考。

import requests
import time

# 12306网站登录信息
username = 'your_username'
password = 'your_password'

# 出发日期、出发城市、到达城市、乘车人信息
date = '2022-01-01'
from_station = '北京'
to_station = '上海'
passengers = [{'name': '张三', 'id': '110101199001010001', 'phone': '13800000000'}]

# 登录12306网站
def login():
    url = 'https://kyfw.12306.cn/otn/login/init'
    session = requests.Session()
    session.get(url)
    login_url = 'https://kyfw.12306.cn/passport/web/login'
    data = {
        'username': username,
        'password': password,
        'appid': 'otn'
    }
    response = session.post(login_url, data=data)
    if response.json()['result_code'] == 0:
        print('登录成功')
        return session
    else:
        print('登录失败')
        return None

# 查询车票信息
def query(session):
    url = f'https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date={date}&leftTicketDTO.from_station={from_station}&leftTicketDTO.to_station={to_station}&purpose_codes=ADULT'
    response = session.get(url)
    data = response.json()['data']
    tickets = []
    for item in data:
        ticket = {}
        ticket['train_no'] = item['queryLeftNewDTO']['train_no']
        ticket['station_train_code'] = item['queryLeftNewDTO']['station_train_code']
        ticket['from_station_name'] = item['queryLeftNewDTO']['from_station_name']
        ticket['to_station_name'] = item['queryLeftNewDTO']['to_station_name']
        ticket['start_time'] = item['queryLeftNewDTO']['start_time']
        ticket['arrive_time'] = item['queryLeftNewDTO']['arrive_time']
        ticket['lishi'] = item['queryLeftNewDTO']['lishi']
        ticket['swz_num'] = item['queryLeftNewDTO']['swz_num']
        ticket['zy_num'] = item['queryLeftNewDTO']['zy_num']
        ticket['ze_num'] = item['queryLeftNewDTO']['ze_num']
        ticket['gr_num'] = item['queryLeftNewDTO']['gr_num']
        ticket['rw_num'] = item['queryLeftNewDTO']['rw_num']
        ticket['yw_num'] = item['queryLeftNewDTO']['yw_num']
        ticket['rz_num'] = item['queryLeftNewDTO']['rz_num']
        ticket['yz_num'] = item['queryLeftNewDTO']['yz_num']
        ticket['wz_num'] = item['queryLeftNewDTO']['wz_num']
        tickets.append(ticket)
    return tickets

# 购买车票
def buy(session, ticket, passenger):
    url = 'https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest'
    data = {
        'secretStr': ticket['secretStr'],
        'train_date': date,
        'back_train_date': date,
        'tour_flag': 'dc',
        'purpose_codes': 'ADULT',
        'query_from_station_name': from_station,
        'query_to_station_name': to_station,
        'undefined': ''
    }
    response = session.post(url, data=data)
    if response.json()['status']:
        print('提交订单成功')
    else:
        print('提交订单失败')
        return False

    time.sleep(1)

    url = 'https://kyfw.12306.cn/otn/confirmPassenger/initDc'
    response = session.get(url)
    token = response.text.split(''globalRepeatSubmitToken'')[1].split('= '')[1].split(''')[0]
    key_check_isChange = response.text.split(''key_check_isChange'')[1].split('= '')[1].split(''')[0]

    url = 'https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs'
    data = {'_json_att': '', 'REPEAT_SUBMIT_TOKEN': token}
    response = session.post(url, data=data)
    passengers = response.json()['data']['normal_passengers']
    passenger = next(filter(lambda x: x['passenger_name'] == passenger['name'], passengers), None)
    if not passenger:
        print('乘车人不存在')
        return False

    url = 'https://kyfw.12306.cn/otn/confirmPassenger/checkOrderInfo'
    data = {
        'cancel_flag': 2,
        'bed_level_order_num': '000000000000000000000000000000',
        'passengerTicketStr': f'O,0,1,{passenger['passenger_name']},1,{passenger['passenger_id_no']},{passenger['mobile_no']},N',
        'oldPassengerStr': f'{passenger['passenger_name']},1,{passenger['passenger_id_no']}',
        'tour_flag': 'dc',
        'randCode': '',
        'whatsSelect': 1,
        '_json_att': '',
        'REPEAT_SUBMIT_TOKEN': token
    }
    response = session.post(url, data=data)
    if response.json()['status']:
        print('校验订单信息成功')
    else:
        print('校验订单信息失败')
        return False

    url = 'https://kyfw.12306.cn/otn/confirmPassenger/getQueueCount'
    data = {
        'train_date': time.strftime('%a %b %d %Y %H:%M:%S', time.strptime(date, '%Y-%m-%d')),
        'train_no': ticket['train_no'],
        'stationTrainCode': ticket['station_train_code'],
        'seatType': 'O',
        'fromStationTelecode': '',
        'toStationTelecode': '',
        'leftTicket': ticket['secretStr'],
        'purpose_codes': '00',
        'train_location': '',
        '_json_att': '',
        'REPEAT_SUBMIT_TOKEN': token
    }
    response = session.post(url, data=data)
    if response.json()['status']:
        print('查询余票信息成功')
    else:
        print('查询余票信息失败')
        return False

    url = 'https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueue'
    data = {
        'passengerTicketStr': f'O,0,1,{passenger['passenger_name']},1,{passenger['passenger_id_no']},{passenger['mobile_no']},N',
        'oldPassengerStr': f'{passenger['passenger_name']},1,{passenger['passenger_id_no']}',
        'randCode': '',
        'purpose_codes': '00',
        'key_check_isChange': key_check_isChange,
        'leftTicketStr': ticket['secretStr'],
        'train_location': '',
        'choose_seats': '',
        'seatDetailType': '',
        'whatsSelect': '1',
        'roomType': '00',
        'dwAll': 'N',
        '_json_att': '',
        'REPEAT_SUBMIT_TOKEN': token
    }
    response = session.post(url, data=data)
    if response.json()['status']:
        print('提交订单成功')
    else:
        print('提交订单失败')
        return False

    url = 'https://kyfw.12306.cn/otn/confirmPassenger/resultOrderForDcQueue'
    data = {
        'orderSequence_no': '',
        '_json_att': '',
        'REPEAT_SUBMIT_TOKEN': token
    }
    while True:
        response = session.post(url, data=data)
        if response.json()['status']:
            if response.json()['data']['submitStatus']:
                print('购票成功')
                return True
            elif response.json()['data']['errMsg']:
                print(response.json()['data']['errMsg'])
                return False
        time.sleep(3)

# 主函数
if __name__ == '__main__':
    session = login()
    if session:
        print('查询车票信息...')
        tickets = query(session)
        if len(tickets) == 0:
            print('无车票信息')
        else:
            for ticket in tickets:
                print(f'{ticket['station_train_code']} {ticket['from_station_name']} -> {ticket['to_station_name']} {ticket['start_time']} - {ticket['arrive_time']}')
                if ticket['swz_num'] != '--':
                    print('商务座有票,购票中...')
                    for passenger in passengers:
                        if buy(session, ticket, passenger):
                            break
                        else:
                            print(f'{passenger['name']} 购票失败')
                    break
                elif ticket['zy_num'] != '--':
                    print('一等座有票,购票中...')
                    for passenger in passengers:
                        if buy(session, ticket, passenger):
                            break
                        else:
                            print(f'{passenger['name']} 购票失败')
                    break
                elif ticket['ze_num'] != '--':
                    print('二等座有票,购票中...')
                    for passenger in passengers:
                        if buy(session, ticket, passenger):
                            break
                        else:
                            print(f'{passenger['name']} 购票失败')
                    break
                else:
                    print('无票信息')
    else:
        print('登录失败')

该程序的实现需要注意以下几点:

  1. 登录12306网站需要使用Session,以保持登录状态。
  2. 查询车票信息需要使用正确的URL和参数,返回的数据需要进行解析。
  3. 购买车票需要分多个步骤进行,每个步骤都需要正确的URL和参数,同时需要注意提交订单和查询订单状态的时间间隔。
  4. 乘车人信息需要提前在12306网站上添加。

虽然该程序可以实现抢票功能,但仍存在一定的风险和局限性。建议在使用前仔细阅读相关法律法规和网站规定,谨慎使用。

Python抢票系统:自动购票脚本实战指南

原文地址: https://www.cveoy.top/t/topic/lAiE 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录