一、引言
12306 是中国铁路客户服务中心的官方网站,提供列车时刻表、余票查询、购票等服务。由于其数据量大且实时性要求高,12306 的后端系统采用了 RESTful API 来提供数据服务。本文将详细介绍如何使用 Python 爬虫技术,通过解析 12306 的 RESTful API 来获取列车信息,并实现余票监控功能。
二、环境准备
在开始之前,需要确保已经安装了以下 Python 库:
可以通过以下命令安装这些库:
pip install requests pandas
三、12306 RESTful API 解析
12306 的 RESTful API 提供了多种接口,用于查询列车信息、余票信息等。以下是一些常用的 API 接口:
- 查询车站信息:获取所有车站的代码和名称。
- 查询列车时刻表:获取指定日期、出发站和到达站的列车信息。
- 查询余票信息:获取指定日期、出发站、到达站和车次的余票信息。
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)
四、余票监控思路
余票监控的核心思路是通过定时任务,定期查询指定日期、出发站和到达站的余票信息,并在有余票时发送通知。以下是一个简单的余票监控实现:
- 设置监控参数:包括出发日期、出发站、到达站、车次、座位类型等。
- 定时查询余票信息:使用
time.sleep()
函数实现定时任务,定期查询余票信息。 - 发送通知:在有余票时,通过邮件、短信等方式发送通知。
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 来获取列车信息,并实现余票监控功能。通过本文的学习,读者可以掌握以下技能:
- 使用
requests
库发送 HTTP 请求,获取 JSON 数据。 - 使用正则表达式解析字符串,提取有用信息。
- 使用
pandas
库进行数据处理和分析。 - 使用
time
库实现定时任务,定期查询余票信息。 - 使用
smtplib
库发送邮件通知。