设为首页收藏本站

Crossin的编程教室

 找回密码
 立即加入
查看: 6233|回复: 0
打印 上一主题 下一主题

今天,你抢到票了吗?

[复制链接]

169

主题

1

好友

733

积分

版主

Rank: 7Rank: 7Rank: 7

跳转到指定楼层
楼主
发表于 2018-7-9 18:16:08 |只看该作者 |倒序浏览

今天网上开始预售除夕前一天的火车票。

这几天,办公室的小伙伴们每天准点蹲在电脑前,不停地刷新页面,可最终还是眼睁睁看着一秒之后就显示“无票”了。(╯‵□′)╯︵┻━┻

无奈之下,只能寄希望于之后几天会有些余票或者退票被放出来。但总不能接下来一直开着网页不停刷吧……好在我们还有 Python 啊,就让程序定时去查咯。

之前也放过查票的代码,参见:
2. 填写出发地和目的地以及出发日后(这里以1月11日上海到北京为例),点击“查询”,在 Network 栏目下,可以看到发出的所有请求。仔细观察后发现,其中一个带有 query 字样的地址就是余票的查询接口,从信息栏中 Headers 分页下的 Request URL 可以看到它的完整地址。

这里注意,12306 现在有两个查询余票的页面,不同页面上看到的接口地址是不一样的。分别是:

旧版:

https://kyfw.12306.cn/otn/lcxxcx/query?purpose_codes=ADULT&queryDate=2017-01-11&from_station=BJP&to_station=BJP


新版:

https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date=2017-01-11&leftTicketDTO.from_station=SHH&leftTicketDTO.to_station=BJP&purpose_codes=ADULT

两个接口的参数和返回值也不相同。这里我们用新版的接口。

在 Python 2 中,我们可以通过 urllib2 直接访问接口,获取返回数据。Python 3 可以使用 urllib.request 或者 requests 库。
  1. req_url = 'https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date=2017-01-11&leftTicketDTO.from_station=SHH&leftTicketDTO.to_station=BJP&purpose_codes=ADULT'
  2. resp = urllib2.urlopen(req_url)
  3. resp_info = resp.read()
  4. print resp_info
复制代码
在程序中输出结果,或者直接在浏览器中打开这个请求地址,可以看到返回值。

如果请求时报错:

<urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)>

需要加上以下代码,忽略 ssl 证书的验证:
  1. import ssl
  2. ssl._create_default_https_context = ssl._create_unverified_context
复制代码

这些密密麻麻看上去有点像是字典格式的数据就是 json 数据。通过浏览器 json 插件或者搜索下 json 在线解析工具,可以让这些数据显示得更人性化。

不难看出,我们需要的车次余票信息就在每一车次全部相关信息中,而这也信息以字典列表的形式,储存在“data”的值中。因此,我们若要查询余票,就该先把 json 格式的数据转为字典,获取其中的 data 列表,然后遍历列表,查询车次,最后从该车次对应的字典字段中,查询余票。
  1. info_json = json.loads(resp_info)
  2. info = info_json['data']
  3. for train_data in info:
  4.     train = train_data['queryLeftNewDTO']
  5.     if train['station_train_code'] == TRAIN:
  6.         print '商务座:', train['swz_num']
  7.         print '特等座', train['tz_num']
  8.         ...
  9.         print '无座', train['wz_num']
  10.         print '其它', train['qt_num']
复制代码
为了让程序一直查询下去,我们用一个条件为 True 的 while 循环。再配合上 time 模块的 sleep 方法(参数单位为秒),让程序每查询一次就休息一会儿。毕竟我们只是想要定时刷一下页面,没必要一直发送请求。
  1. while True:
  2.     # 查询余票代码
  3.     time.sleep(600)
复制代码
现在,在你的电脑上运行代码,就可以每隔 10 分钟自动去访问一次页面,看看是否有新的余票放出。当然,你得根据自己的需要,去修改请求地址里的日期和出发、到达站的代号。

在公众号『Crossin的编程教室』(crossincode)里回复 查票,获取本篇的完整示例代码。

如果你还希望程序在刷出票后,能给你发个邮件提醒的话,请查看我们之前的文章:
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即加入

QQ|手机版|Archiver|Crossin的编程教室 ( 苏ICP备15063769号  

GMT+8, 2024-12-4 01:34 , Processed in 0.024509 second(s), 24 queries .

Powered by Discuz! X2.5

© 2001-2012 Comsenz Inc.

回顶部