Python爬虫实战指南:爬取12306列车信息——RESTful API解析与余票监控攻略

一、引言

12306 是中国铁路客户服务中心的官方网站,提供列车时刻表、余票查询、购票等服务。由于其数据量大且实时性要求高,12306 的后端系统采用了 RESTful API 来提供数据服务。本文将详细介绍如何使用 Python 爬虫技术,通过解析 12306 的 RESTful API 来获取列车信息,并实现余票监控功能。

二、环境准备

在开始之前,需要确保已经安装了以下 Python 库:

  • requests:用于发送 HTTP 请求。
  • json:用于解析 JSON 数据。
  • pandas:用于数据处理和分析。
  • time:用于实现定时任务。
  • 可以通过以下命令安装这些库:

    pip install requests pandas
    

    三、12306 RESTful API 解析

    12306 的 RESTful API 提供了多种接口,用于查询列车信息、余票信息等。以下是一些常用的 API 接口:

    1. 查询车站信息:获取所有车站的代码和名称。
    2. 查询列车时刻表:获取指定日期、出发站和到达站的列车信息。
    3. 查询余票信息:获取指定日期、出发站、到达站和车次的余票信息。

    1、查询车站信息

    12306 提供了一个接口用于获取所有车站的代码和名称。该接口的 URL 如下:

    url = "https://kyfw.12306.cn/otn/resources/js/framework/station_name.js"
    

    通过发送 HTTP GET 请求,可以获取到车站信息的 JavaScript 文件。该文件中的内容是一个字符串,包含了所有车站的代码和名称。可以通过正则表达式解析该字符串,提取出车站信息。

    import re
    import requests
    
    def get_station_info():
        url = "https://kyfw.12306.cn/otn/resources/js/framework/station_name.js"
        response = requests.get(url)
        station_str = response.text
        station_list = re.findall(r'([\u4e00-\u9fa5]+)\|([A-Z]+)', station_str)
        station_dict = {station[1]: station[0] for station in station_list}
        return station_dict
    
    station_dict = get_station_info()
    print(station_dict)
    

    2、查询列车时刻表

    查询列车时刻表的接口 URL 如下:

    url = "https://kyfw.12306.cn/otn/leftTicket/query"
    

    该接口需要以下参数:

  • leftTicketDTO.train_date:出发日期,格式为 YYYY-MM-DD
  • leftTicketDTO.from_station:出发站代码。
  • leftTicketDTO.to_station:到达站代码。
  • purpose_codes:乘客类型,ADULT 表示成人。
  • 通过发送 HTTP GET 请求,可以获取到指定日期、出发站和到达站的列车信息。返回的数据是 JSON 格式,包含了列车的车次、出发时间、到达时间、历时、余票等信息。

    import json
    
    def get_train_schedule(date, from_station, to_station):
        url = "https://kyfw.12306.cn/otn/leftTicket/query"
        params = {
            "leftTicketDTO.train_date": date,
            "leftTicketDTO.from_station": from_station,
            "leftTicketDTO.to_station": to_station,
            "purpose_codes": "ADULT"
        }
        response = requests.get(url, params=params)
        data = json.loads(response.text)
        return data['data']['result']
    
    date = "2023-10-01"
    from_station = "BJP"  # 北京
    to_station = "SHH"  # 上海
    train_schedule = get_train_schedule(date, from_station, to_station)
    print(train_schedule)
    

    3、查询余票信息

    查询余票信息的接口 URL 如下:

    url = "https://kyfw.12306.cn/otn/leftTicket/queryTicketPrice"
    

    该接口需要以下参数:

  • train_no:车次编号。
  • from_station_no:出发站编号。
  • to_station_no:到达站编号。
  • seat_types:座位类型,O 表示二等座,M 表示一等座,9 表示商务座。
  • train_date:出发日期,格式为 YYYY-MM-DD
  • 通过发送 HTTP GET 请求,可以获取到指定日期、出发站、到达站和车次的余票信息。返回的数据是 JSON 格式,包含了不同座位类型的余票数量和价格。

    def get_ticket_price(train_no, from_station_no, to_station_no, seat_types, date):
        url = "https://kyfw.12306.cn/otn/leftTicket/queryTicketPrice"
        params = {
            "train_no": train_no,
            "from_station_no": from_station_no,
            "to_station_no": to_station_no,
            "seat_types": seat_types,
            "train_date": date
        }
        response = requests.get(url, params=params)
        data = json.loads(response.text)
        return data['data']
    
    train_no = "G1"
    from_station_no = "01"
    to_station_no = "02"
    seat_types = "O"
    date = "2023-10-01"
    ticket_price = get_ticket_price(train_no, from_station_no, to_station_no, seat_types, date)
    print(ticket_price)
    

    四、余票监控思路

    余票监控的核心思路是通过定时任务,定期查询指定日期、出发站和到达站的余票信息,并在有余票时发送通知。以下是一个简单的余票监控实现:

    1. 设置监控参数:包括出发日期、出发站、到达站、车次、座位类型等。
    2. 定时查询余票信息:使用 time.sleep() 函数实现定时任务,定期查询余票信息。
    3. 发送通知:在有余票时,通过邮件、短信等方式发送通知。
    import time
    import smtplib
    from email.mime.text import MIMEText
    
    def send_email(subject, content):
        mail_host = "smtp.163.com"
        mail_user = "your_email@163.com"
        mail_pass = "your_password"
        sender = "your_email@163.com"
        receivers = ["receiver_email@163.com"]
    
        message = MIMEText(content, 'plain', 'utf-8')
        message['Subject'] = subject
        message['From'] = sender
        message['To'] = receivers[0]
    
        try:
            smtpObj = smtplib.SMTP()
            smtpObj.connect(mail_host, 25)
            smtpObj.login(mail_user, mail_pass)
            smtpObj.sendmail(sender, receivers, message.as_string())
            smtpObj.quit()
            print("邮件发送成功")
        except smtplib.SMTPException as e:
            print("邮件发送失败", e)
    
    def monitor_ticket(date, from_station, to_station, train_no, seat_types):
        while True:
            ticket_price = get_ticket_price(train_no, from_station, to_station, seat_types, date)
            if ticket_price[seat_types] > 0:
                subject = "余票通知"
                content = f"车次 {train_no} 的 {seat_types} 座位有余票,请尽快购买!"
                send_email(subject, content)
                break
            time.sleep(60)
    
    date = "2023-10-01"
    from_station = "BJP"  # 北京
    to_station = "SHH"  # 上海
    train_no = "G1"
    seat_types = "O"
    monitor_ticket(date, from_station, to_station, train_no, seat_types)
    

    五、数据处理与分析

    获取到的列车信息和余票信息通常是 JSON 格式,可以使用 pandas 库将其转换为 DataFrame,方便进行数据处理和分析。

    import pandas as pd
    
    def parse_train_schedule(train_schedule):
        data = []
        for train in train_schedule:
            train_info = train.split('|')
            data.append({
                '车次': train_info[3],
                '出发站': station_dict[train_info[6]],
                '到达站': station_dict[train_info[7]],
                '出发时间': train_info[8],
                '到达时间': train_info[9],
                '历时': train_info[10],
                '余票': train_info[11]
            })
        df = pd.DataFrame(data)
        return df
    
    df = parse_train_schedule(train_schedule)
    print(df)
    

    六、总结

    本文详细介绍了如何使用 Python 爬虫技术,通过解析 12306 的 RESTful API 来获取列车信息,并实现余票监控功能。通过本文的学习,读者可以掌握以下技能:

    1. 使用 requests 库发送 HTTP 请求,获取 JSON 数据。
    2. 使用正则表达式解析字符串,提取有用信息。
    3. 使用 pandas 库进行数据处理和分析。
    4. 使用 time 库实现定时任务,定期查询余票信息。
    5. 使用 smtplib 库发送邮件通知。

    Python爬虫实战

    作者:yansideyucsdn

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python爬虫实战指南:爬取12306列车信息——RESTful API解析与余票监控攻略

    发表回复