c语言编程笔录

您现在的位置是:首页 > 编程 > 编程经验

编程经验

python的查车票小工具python购买火车票

林家纶 2023-07-13编程经验
需求概述这是一个基于Python的火车票查询与购买小工具,主要包括两个功能:通过查询火车票余票信息,告知用户当前车次的余票情况,并支持实时提醒;自动登录12306网站,

需求概述

这是一个基于Python的火车票查询与购买小工具,主要包括两个功能:通过查询火车票余票信息,告知用户当前车次的余票情况,并支持实时提醒;自动登录12306网站,查询指定的出发时间、路线和座位类型的车票,并完成购买。

第一功能:火车票余票查询

实现火车票余票查询功能,主要需要搭建自己的查询接口,并根据接口返回的信息进行处理和展示。以下是一个简单的查询余票的Python代码示例:

import requests
from pyquery import PyQuery as pq

def queryTicket(train_no, from_station, to_station, date):
    query_url = 'https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date={}&leftTicketDTO.from_station={}&leftTicketDTO.to_station={}&purpose_codes=ADULT'.format(date, from_station, to_station)
    res = requests.get(query_url, verify=False)
    if res.status_code == requests.codes.ok:
        data = res.json()
        tickets = {}
        for item in data['data']['result']:
            ticket_info = item.split('|')
            train_code = ticket_info[3]
            if train_code == train_no:
                arrive_time = ticket_info[8]
                left_time = ticket_info[9]
                seatTypes = [
                    {'name': '商务座', 'type': 'A9'},
                    {'name': '一等座', 'type': 'M'},
                    {'name': '二等座', 'type': 'O'},
                    {'name': '软卧', 'type': 'A4'},
                    {'name': '硬卧', 'type': 'A3'},
                    {'name': '硬座', 'type': 'A1'},
                    {'name': '无座', 'type': 'WZ'}
                ]
                seat_infos = {}
                for seat in seatTypes:
                    if ticket_info[seat['type']] != '无' and ticket_info[seat['type']] != '':
                        seat_info = {'name': seat['name'], 'count': ticket_info[seat['type']]}
                        seat_infos.update({seat['type']: seat_info})
                return {'train_code': train_code, 'arrive_time': arrive_time, 'left_time': left_time, 'seat_infos': seat_infos}
    return None

# 样例调用
queryTicket('D1', 'BJP', 'SHH', '2018-10-01')

通过以上代码实现了查询余票的逻辑,其中train_no是指定的车次,from_station和to_station是相应的出发站和到达站的电报码,date是出发日期。代码首先构造了查询url,然后进行了接口调用,将返回数据封装到字典中进行处理,最后返回火车票的余票信息。

第二功能:火车票自动购买

自动购买火车票需要模拟用户在12306网站的登录和购买流程。首先需要访问12306的登录页面,获取动态生成的登录token,并根据用户名和密码生成加密后的密码,最后提交请求进行登录。接下来是购票过程,通过查询余票接口获取可用余票的信息,然后进行当前出发站和到达站的选择、座位类型的选择、乘客信息的填写、验证码的处理等步骤,完成相应的购票动作。以下是一个简单的Python代码示例:

import time
import requests
from pyquery import PyQuery as pq
from urllib.parse import urlencode

class TrainTickets:
    def __init__(self):
        self.login_url = 'https://kyfw.12306.cn/passport/web/login'
        self.index_url = 'https://kyfw.12306.cn/otn/index/initMy12306'
        self.order_url = 'https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest'
        self.initdc_url = 'https://kyfw.12306.cn/otn/confirmPassenger/initDc'
        self.check_order_url = 'https://kyfw.12306.cn/otn/confirmPassenger/checkOrderInfo'
        self.confirm_order_url = 'https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueue'
        self.login_data = {
            'username': username,
            'password': password,
            'appid': 'otn'
        }
        self.passenger_name = passenger_name
        self.from_station = from_station
        self.to_station = to_station
        self.seat_type = seat_type
        self.depart_date = depart_date
        self.ticket_info = None
        self.token = None
        self.session = requests.Session()

    def login(self):
        self.session.post(self.login_url, data=self.login_data, headers=headers)
        resp = self.session.get(self.index_url, headers=headers)
        doc = pq(resp.text)
        my_name = doc('#my12306menu > div > div.welcome-info > span').text()
        if my_name:
            print('登录成功')
        else:
            print('登录失败')

    def get_train_info(self):
        query_url = 'https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date={}&leftTicketDTO.from_station={}&leftTicketDTO.to_station={}&purpose_codes=ADULT'.format(self.depart_date, self.from_station, self.to_station)
        res = self.session.get(query_url, verify=False)
        if res.status_code == 200:
            data = res.json()
            for item in data['data']['result']:
                ticket_info = item.split('|')
                train_code = ticket_info[3]
                if train_code == self.train_no:
                    # 解析余票信息
                    ...

    def submit_order(self):
        data = {
            'secretStr': self.ticket_info['secretStr'],
            'train_date': self.ticket_info['date'],
            'back_train_date': self.ticket_info['date'],
            'tour_flag': 'dc',
            'purpose_codes': 'ADULT',
            'query_from_station_name': self.from_station,
            'query_to_station_name': self.to_station,
            'undefined':''
        }
        submit_url = self.order_url + '?' + urlencode(data)
        res = self.session.post(submit_url)
        if res.status_code == requests.codes.ok:
            print('订票成功')
        else:
            print('订票失败')

    def init_dc(self):
        data = {
            '_json_att': '',
            'REPEAT_SUBMIT_TOKEN': self.token
        }
        res = self.session.post(self.initdc_url, data=data, headers=headers, verify=False)
        if res.status_code == 200:
            print('确认乘客')

    def check_order_info(self):
        passenger_data = {
            'REPEAT_SUBMIT_TOKEN': self.token,
            'checkBox': 'Y',
            'bed_level_order_num': '000000000000000000000000000000',
            'passengerTicketStr': 'O,0,1,{},1,{},{},N'.format(self.passenger_name, self.ticket_info['seat_type']),
            'oldPassengerStr': '{},1,1,{}'.format(self.passenger_name, self.cert_no)
        }
        data = {
            'cancel_flag': '2',
            'bed_level_order_num': '000000000000000000000000000000',
            'tour_flag': 'dc',
            'randCode': '',
            '_json_att': '',
            'REPEAT_SUBMIT_TOKEN': self.token
        }
        res = self.session.post(self.check_order_url, data=data, headers=headers, verify=False)
        if res.status_code == 200:
            if res.json()['data']['submitStatus']:
                print('提交成功')

    def confirm_order(self):
        passenger_data = {
            'REPEAT_SUBMIT_TOKEN': self.token,
            'checkBox': 'Y',
            'bed_level_order_num': '000000000000000000000000000000',
            'passengerTicketStr': 'O,0,1,{},,1,{},{},N'.format(self.passenger_name, self.ticket_info['seat_type']),
            'oldPassengerStr': '{},1,1,{}'.format(self.passenger_name, self.cert_no)
        }
        data = {
            'passengerTickets': passenger_data['passengerTicketStr'],
            'oldPassengers': passenger_data['oldPassengerStr'],
            'randCode': '',
            'purpose_codes': '00',
            'key_check_isChange': '',
            'leftTicketStr': self.ticket_info['secretStr'],
            'train_location': self.ticket_info['train_location'],
            'choose_seats': '',
            'seatDetailType': '000',
            'whatsSelect': '1',
            'roomType': '00',
            'dwAll': 'N',
            '_json_att': '',
            'REPEAT_SUBMIT_TOKEN': self.token
        }
        res = self.session.post(self.confirm_order_url, data=data, headers=headers, verify=False)
        if res.status_code == 200:
            data = res.json()
            if data['data']['submitStatus']:
                print('购买成功')

ticket = TrainTickets()
ticket.login()
ticket.get_train_info()
ticket.submit_order()
ticket.init_dc()
ticket.check_order_info()
ticket.confirm_order()

以上是一个模拟12306网站登录和购票流程的Python代码示例,代码中需要填写的部分主要是用户名、密码、乘客名、证件号、出发站电报码、到达站电报码、座位类型和出发日期。模拟登录过程中需要通过正则表达式或者PyQuery等工具获取动态生成的登录token和相应cookie信息。

总结

本文简述了一个基于Python的火车票查询与购买小工具,其中包括两个主要的功能:火车票余票查询和火车票自动购买。通过以上代码示例,我们可以看到,Python作为一种全栈语言,在处理Web开发、网络编程和数据处理等方面都有其独特的优势,而在实现此类自动化工具方面,Python更是表现出其便捷和高效的特点。

文章评论