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爬虫实战

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值