python:12306余票爬虫

本文介绍了如何分析12306余票查询的网页,提取所需参数,并通过编写Python代码实现从12306 API获取余票信息的过程。详细阐述了从获取车站缩写到解析JSON数据的步骤,最终实现输出各班次的余票详情。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

12306余票爬虫

1.网页分析
1.1
打开12306余票查询的界面(https://kyfw.12306.cn/otn/leftTicket/init)。普通查询需要输入出发地,目的地和时间,试着输入一下。
1.2
信息更新,页面没有跳转。看下发包情况。
1.3
发现有个包带有’queryX’字段,一看就非常可疑,点开看看。
这里写图片描述
1.4
ok,这就是我们要的余票信息,不急,先回头解析这余票信息API。
这里写图片描述
1.5
截去地址前段,留下部分可拆为:
leftTicketDTO.train_date=2017-10-07
&leftTicketDTO.from_station=BJP
&leftTicketDTO.to_station=CQW
&purpose_codes=ADULT
四个参数,用途一目了然。但车站信息是用三位大写字母表示的,包数据里也没有相关内容,有点头疼。
1.6
回到网页找线索。在站点名称输入框出发现值:from_station_name。尝试搜索station_name,有眉目了。
这里写图片描述

这里写图片描述
1.7
补上12306的前段地址,看看情况。这密密麻麻的一片,就是我们要的缩写数据。
这里写图片描述
1.8
材料备齐,开工撸代码。

2.代码实现
2.1
输入:出发地,目的地,时间
输出:各班次的余票信息
过程:将输入信息转化API需要格式——利用API提取各班次信息——分析整理后输出
2.2
根据先前的网页分析,为利用API,我们还需要将站点的汉字名改为对应的三位ABC缩写。对应数据存储于:https://kyfw.12306.cn/otn/resources/js/framework/station_name.js。观察发现,汉字名和ABC缩写的相对位置固定,可以index()汉字位置后,直接切片提取ABC缩写。(12306网站有个自签证书,用requests连接获取数据时需要跳过ssl验证。)

#info_str为网页存储的站点信息。
Station_index = info_str.index("|%s|" %(Station)) +2 +len(Station)
Station_ABC = info_str[Station_index: Station_index + 3]

2.3
尝试将转化后的信息,输入余票信息API,成功(12306有对应频繁获取反制机制,之前次数过多可能无法正常获取信息,要稍等一会)。
2.4
利用python的json库记载余票信息json包。其中我们最关心的余票数据,存储在’data’内的‘result’,格式是一长串字符串,各数据用‘|’间隔开。我们要的做的就是提取之,切割成list方便我们提取对应数据。

#r.text为网页存储的余票json包
ticket_dict = json.loads(r.text)
test_str = a['data']['result']
info_list = tarin_info.split('|')

2.5
写个计数器,遍历一遍每个班次信息的list。多对比下网页的余票内容,我们可以很容易猜到list中各项信息的含义。
这里写图片描述
2.6
找到我们要的内容,提取出来,按简易格式打印出来,工作就完成啦。
这里写图片描述

3.个人代码

import requests
import json

def getStationABC(Station):
    info_url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js'
    r = requests.get(info_url,verify=False)
    info_str = r.text
    Station_index = info_str.index("|%s|" %(Station)) +2 +len(Station)
    Station_ABC = info_str[Station_index: Station_index + 3]
    return Station_ABC

def getTicketText(FromStation_ABC,ToStation_ABC,Date):
    query_url = "https://kyfw.12306.cn/otn/leftTicket/queryX?\
leftTicketDTO.train_date=%s\
&leftTicketDTO.from_station=%s\
&leftTicketDTO.to_station=%s\
&purpose_codes=ADULT" %(str(Date),FromStation_ABC,ToStation_ABC)
    r = requests.get(query_url,verify=False)
    ticket_dict = json.loads(r.text)
    try:
        test_str = ticket_dict['data']['result']
    except KeyError:
        print('获取信息失败,请稍后重试')
    for tarin_info in test_str:
        info_list = tarin_info.split('|')
        count = 0
        print('---- 车次:' + info_list[3] + '-----------------------------')
        print('出发时间:' + info_list[8])
        print('到站时间:' + info_list[9])
        print('旅程时间:' + info_list[10])
        print('商务座特等座:'+info_list[32])
        print('一等座:' + info_list[31])
        print('二等座:' + info_list[30])
        print('软卧:' + info_list[23])
        print('无座:' + info_list[26])
        print('硬卧:' + info_list[28])       
        print('硬座:' + info_list[29])  

if __name__ == '__main__':
    FromStation = input('请输入出发地:')
    ToStation = input('请输入目的地:')
    Date = input('请输入日期(格式:2017-10-09)')
    FromStation_ABC = getStationABC(FromStation)
    ToStation_ABC = getStationABC(ToStation)
    print('目的地:%s;出发地:%s;日期:%s。' %(FromStation,ToStation,Date))
    getTicketText(FromStation_ABC,ToStation_ABC,Date)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值