12306火车票查询--Python可以这么玩!!!

简介: 12306火车票查询--Python可以这么玩!!!

本期导读

火车票查询的平台有很多,比如携程、去哪儿,飞猪等等,但是万变不离其宗,所有平台的数据都需要从12306官网获取,只是通过前端的渲染以不同的形式展现出来而已,本期通过分析12306官网网页结构,利用python进行火车票信息查询,并将信息格式化输出、保存到本地Excel文件。

01

打开12306官网,输入出发地、目的地、出发日期进行查询,这里我们查询 2021-02-21 北京-武汉的车票信息。

右键选择审查元素,查看所有车次信息都在一个表格(table)标签中:

02

接下来我们直接把网址复制出来用python请求测试一下返回结果:


url = 'https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc&fs=%E5%8C%97%E4%BA%AC,BJP&ts=%E6%AD%A6%E6%B1%89,WHN&date=2021-02-21&flag=N,N,Y'
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
    'Cookie': '你的 cookie'
}
r = requests.get(url, headers=headers, timeout=10)
r.raise_for_status()
r.encoding = r.apparent_encoding
print(r.text)

在返回信息中任意查询一个车次,比如G507:

很奇怪,明明在页面table中可以看到,但是网页请求返回信息中却没有,所以猜测可能是异步请求,真正的车次信息在其它接口中返回。

03

重新分析一下网页源码,在Network的XHR(为什么会直接找XHR,其实XHR是XMLHttpRequest的缩写,我们与网页的交互记录都在这里面,所以我们直接找请求的XHR信息)中看到如下一条交互信息:

再次在返回信息中查询车次G507:

果不其然,G507车次信息在这里,搜索其他车次,发现也可以找得到,仔细分析一下这个返回信息会发现车次,出发站到达站,出发时间到达时间等等信息都在这里,简直是意外收获!

04

检查Header信息,实际请求网址为:

https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date=2021-02-21&leftTicketDTO.from_station=BJP&leftTicketDTO.to_station=WHN&purpose_codes=ADULT

根据新的域名和参数再次请求:

这样我们就拿到了所有车次的信息,接下来就是解析这个json格式的数据,获取详细的车次信息了。

05

全部车次的信息在data关键字的result列表中,result共有52条(包含停运列车)信息和12306网站上显示的信息一致,遍历result列表即可获取每个车次的车票信息。


r = requests.get(url, headers=headers, timeout=10)
r.raise_for_status()
r.encoding = r.apparent_encoding
print(r.text)
raw_trains = json.loads(r.text)['data']['result']
allinfo = []
for raw_train in raw_trains:
    oneinfo = []
    # split切割之后得到的是一个列表
    data_list = raw_train.split("|")
    # 车次
    train_no = data_list[3]
    # 出发站
    from_station_code = data_list[6]
    # 到达站
    to_station_code = data_list[7]  
    from_station_name =     stations.get_name(from_station_code)
    to_station_name = stations.get_name(to_station_code)    # 出发时间
    start_time = data_list[8]
    # 到达时间
    arrive_time = data_list[9]
    # 历时    
    time_duration = data_list[10]
    # 商务座
    business_seat = data_list[32] or '--'
    # 一等座
    first_class_seat = data_list[31] or "--"
    # 二等座
    second_class_seat = data_list[30] or "--"  
    # 高级软卧
    g_soft_sleep = data_list[21] or "--"  
    # 软卧
    soft_sleep = data_list[23] or "--"  
    # 动卧
    d_soft_sleep = data_list[27] or "--"  
    # 硬卧
    hard_sleep = data_list[28] or "--"  
    # 软座
    soft_seat = data_list[24] or "--" 
    # 硬座
    hard_seat = data_list[29] or "--"  
    # 无座
    no_seat = data_list[26] or '--'  
    if time_duration == '99:59' and start_time == '24:00' and arrive_time == '24:00':
        train_no = train_no + '(列车停运)'
        continue
    oneinfo.append(train_no)
    oneinfo.append(from_station_name)
    oneinfo.append(to_station_name)
    oneinfo.append(start_time)
    oneinfo.append(arrive_time)
    oneinfo.append(time_duration)
    oneinfo.append(business_seat)
    oneinfo.append(first_class_seat)
    oneinfo.append(second_class_seat)
    oneinfo.append(g_soft_sleep)
    oneinfo.append(soft_sleep)
    oneinfo.append(d_soft_sleep)
    oneinfo.append(hard_sleep)
    oneinfo.append(soft_seat)
    oneinfo.append(hard_seat)
    oneinfo.append(no_seat)
    allinfo.append(oneinfo)

上面对应的信息编号需要根据返回列表比对确认,代码是解析全部信息,如果只需要部分信息的话直接筛选即可,注意处理过程中我们将停运列车信息去掉(根据自己需要也可以保留,将continue注释掉即可)。

06

格式化输出车次信息:


strr = "车次 车站 时间 经历时 商务座 一等座 二等座 高级软卧 软卧 动卧 硬卧  软座 硬座 无座"
lst = strr.split()
pt = PrettyTable(field_names=lst)
pt.add_row([
    # 对特定文字添加颜色
    Fore.LIGHTYELLOW_EX + train_no + Fore.RESET,
    '\n'.join([Fore.GREEN + stations.get_name(from_station_code) + Fore.RESET,
               Fore.RED + stations.get_name(to_station_code) + Fore.RESET]),
    '\n'.join([Fore.GREEN + start_time + Fore.RESET, Fore.RED + arrive_time + Fore.RESET]),
    time_duration,
    business_seat,
    first_class_seat,
    second_class_seat,
    g_soft_sleep,
    soft_sleep,
    d_soft_sleep,
    hard_sleep,
    soft_seat,
    hard_seat,
    no_seat
])
print(pt)


输出如下:

提示:prettytable 这个库对中文兼容性不算太友好,所以内容中包含中文时,文本对齐会出现一定偏差,如果替换成相应英文名称的话会更美观,大家也可以尝试用print制表符的方式来格式化输出。

07

保存车次信息到本地Excel文件:


def Insert2Excel(allinfo,xlname):
    tableTitle = ['车次','出发站','到达站','出发时间','到站时间','经历时','商务座','一等座','二等座','高级软卧','软卧','动卧','硬卧','软座','硬座','无座']
    wb = Workbook()
    ws = wb.active
    ws.title = 'sheet1'
    # 添加表头
    ws.append(tableTitle)
    work_name = xlname + '.xlsx'
    # 设置格式
    for i in range(1, ws.max_column + 1):
        ws[get_column_letter(i)+'1'].font = Font( bold=True)
        ws.column_dimensions[get_column_letter(i)].width = 10
        ws.column_dimensions[get_column_letter(i)].alignment = Alignment(horizontal='left', vertical='center')
    # 插入数据
    for info in allinfo :
        ws.append(info)
    ws.freeze_panes = 'A2'
    # 保存文件
    wb.save(work_name)


Excel 文件的首行做了加粗和冻结的简单处理,更多方法可以查阅openpyxl库的使用方法。

大功告成!大家也可以将出发站、到达站和查询日期以input输入的方式来操作,注意请求url需要进行拼接处理。


END

以上就是本期为大家整理的全部内容了,码字不易,喜欢的朋友可以点赞、点在看也可以分享到朋友圈让更多人知道哦

相关文章
|
1月前
|
Python
Python实现简易天气查询系统
Python实现简易天气查询系统
60 4
|
8天前
|
关系型数据库 数据库连接 数据库
Python执行PG数据库查询语句:以Markdown格式打印查询结果
使用Python的`psycopg2`和`pandas`库与PostgreSQL交互,执行查询并以Markdown格式打印结果。首先确保安装所需库:`pip install psycopg2 pandas`。接着建立数据库连接,执行查询,将查询结果转换为DataFrame,再用`tabulate`库将DataFrame格式化为Markdown。代码示例包括连接函数、查询函数、转换和打印函数。最后限制列宽以适应输出。
|
28天前
|
数据采集 JSON 数据挖掘
2024年利用Python查询IP地址_怎么查python文件中ip地址,2024年最新15个经典面试问题及答案英语
2024年利用Python查询IP地址_怎么查python文件中ip地址,2024年最新15个经典面试问题及答案英语
|
8天前
|
SQL 关系型数据库 数据库
Python查询PostgreSQL数据库
木头左教你如何用Python连接PostgreSQL数据库:安装`psycopg2`库,建立连接,执行SQL脚本如创建表、插入数据,同时掌握错误处理和事务管理。别忘了性能优化,利用索引、批量操作提升效率。下期更精彩!💡 csvfile
Python查询PostgreSQL数据库
|
8天前
|
SQL 关系型数据库 数据库
Python执行PostgreSQL数据库查询语句,并打印查询结果
本文介绍了如何使用Python连接和查询PostgreSQL数据库。首先,确保安装了`psycopg2`库,然后创建数据库连接函数。接着,展示如何编写SQL查询并执行,例如从`employees`表中选取所有记录。此外,还讨论了处理查询结果、格式化输出和异常处理的方法。最后,提到了参数化查询和事务处理以增强安全性及确保数据一致性。
Python执行PostgreSQL数据库查询语句,并打印查询结果
|
1月前
|
Python
【Python3 查询手册学习】,完整版PDF开放下载_python速查手册·模块卷(全彩版) pdf(1)
【Python3 查询手册学习】,完整版PDF开放下载_python速查手册·模块卷(全彩版) pdf(1)
|
1月前
|
JSON 数据格式 索引
python之JMESPath:JSON 查询语法库示例详解
python之JMESPath:JSON 查询语法库示例详解
22 0
|
1月前
|
开发者 Python
在Python中查询进程信息的实用指南
在Python中查询进程信息的实用指南
19 2
|
1月前
|
SQL 缓存 数据库
在Python Web开发过程中:数据库与缓存,如何使用ORM(例如Django ORM)执行查询并优化查询性能?
在Python Web开发中,使用ORM如Django ORM能简化数据库操作。为了优化查询性能,可以:选择合适索引,避免N+1查询(利用`select_related`和`prefetch_related`),批量读取数据(`iterator()`),使用缓存,分页查询,适时使用原生SQL,优化数据库配置,定期优化数据库并监控性能。这些策略能提升响应速度和用户体验。
25 0
|
1月前
|
数据采集 搜索推荐 数据挖掘
使用Python制作一个批量查询搜索排名的SEO免费工具
最近工作中需要用上 Google SEO(搜索引擎优化),有了解过的朋友们应该都知道SEO必不可少的工作之一就是查询关键词的搜索排名。关键词少的时候可以一个一个去查没什么问题,但是到了后期,一个网站都有几百上千的关键词,你再去一个一个查,至少要花费数小时的时间。 虽然市面上有很多SEO免费或者收费工具,但免费的基本都不能批量查,网上免费的最多也就只能10个10个查询,而且查询速度很慢。收费的工具如Ahrefs、SEMrush等以月为单位收费最低也都要上百美刀/月,当然如果觉得价格合适也可以进行购买,毕竟这些工具的很多功能都很实用。今天我给大家分享的这个排名搜索工具基于python实现,当然肯定
60 0