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月前
|
测试技术 API 数据安全/隐私保护
Python连接到Jira实例、登录、查询、修改和创建bug
通过使用Python和Jira的REST API,可以方便地连接到Jira实例并进行各种操作,包括查询、修改和创建Bug。`jira`库提供了简洁的接口,使得这些操作变得简单易行。无论是自动化测试还是开发工作流的集成,这些方法都可以极大地提高效率和准确性。希望通过本文的介绍,您能够更好地理解和应用这些技术。
120 0
|
2月前
|
iOS开发 MacOS Python
Python编程小案例—利用flask查询本机IP归属并输出网页图片
Python编程小案例—利用flask查询本机IP归属并输出网页图片
26 1
|
3月前
|
关系型数据库 MySQL 数据库
Python MySQL查询返回字典类型数据的方法
通过使用 `mysql-connector-python`库并选择 `MySQLCursorDict`作为游标类型,您可以轻松地将MySQL查询结果以字典类型返回。这种方式提高了代码的可读性,使得数据操作更加直观和方便。上述步骤和示例代码展示了如何实现这一功能,希望对您的项目开发有所帮助。
159 4
|
3月前
|
存储 Python
深度剖析:Python里字典树Trie的构建与查询,让你的代码更优雅!
在编程的世界里,数据结构的选择往往直接决定了程序的效率和可读性。今天,我们将深入探索一种高效处理字符串搜索与匹配的数据结构——字典树(Trie),也称作前缀树或单词查找树。通过Python实现Trie树,我们将看到它如何优雅地解决一系列字符串相关的问题,并提升代码的整体质量。
46 2
|
2月前
|
SQL 前端开发 Python
基于python-django的neo4j人民的名义关系图谱查询系统
基于python-django的neo4j人民的名义关系图谱查询系统
38 0
|
2月前
|
IDE 搜索推荐 网络安全
Python编程:编写被动信息搜集之网址的IP及Whois查询
Python编程:编写被动信息搜集之网址的IP及Whois查询
33 0
|
4月前
|
测试技术 API 开发者
Python 魔法:打造你的第一个天气查询小工具自动化测试框架的构建与实践
【8月更文挑战第31天】在这篇文章中,我们将一起踏上编程的奇妙旅程。想象一下,只需几行代码,就能让计算机告诉你明天是否要带伞。是的,你没有听错,我们将用Python这把钥匙,解锁天气预报的秘密。不论你是编程新手还是想拓展技能的老手,这篇文章都会为你带来新的视角和灵感。所以,拿起你的键盘,让我们一起创造属于自己的天气小工具吧!
|
3月前
|
数据采集 自然语言处理 数据挖掘
python查询汉字函数
简洁、高效、易懂的代码对于提高开发效率与项目质量至关重要,并且对于维持代码的可读性和可维护性也有着很大帮助。选择正确的工具和方法可以大幅提升处理中文数据的效率。在编写用户定义函数时,明确函数的功能与返回值类型对于函数的复用和调试也同样重要。当涉及到复杂的文本处理或数据分析时,不宜过分依赖单一的工具或方法,而应根据具体需求灵活选择和组合不同的技术手段。
40 0
|
4月前
|
搜索推荐 API 数据处理
Python魔法:打造个性化天气查询工具
【8月更文挑战第31天】 在这篇文章中,我们将一起探索如何用Python构建一个个性化的天气查询工具。不同于传统的技术文章,我们将通过一个简单的故事引入主题,让读者感受到编程的乐趣和实用性。文章将介绍如何使用API获取数据,处理这些数据,并以用户友好的方式展示信息。无论你是编程新手还是想扩展你的项目库,这篇文章都会给你提供有价值的见解和代码示例。
|
4月前
|
JSON IDE API
探索Python编程:打造你的第一个天气查询工具
【8月更文挑战第30天】在这篇文章中,我们将一起踏上Python编程的奇妙旅程,从零基础开始,逐步构建出属于自己的天气查询工具。文章将引导你了解Python语言的魅力,通过实际的项目操作,让你体验到编程的乐趣和成就感。无论你是编程新手还是希望扩展技能的老手,这篇文章都将为你提供宝贵的经验和知识。让我们一起探索代码的世界,解锁新技能,让技术改变生活!