python实现命令行火车票查看器--参考实验楼文档

程序运行效果图:


首先简单介绍下用到的2个重要的库:requests和docopt,可使用命令pip install requests docopt进行安装。

  • requests是一个很实用的Python HTTP客户端库,编写爬虫和测试服务器响应数据时经常会用到。
  • docopt 命令行参数解析库,docopt 本质上是在 Python 中引入了一种针对命令行参数的形式语言,需实现两个部分:1、在代码的最开头使用 """ """文档注释的形式写出符合要求的文档,就会自动生成对应的parse;2、在代码执行中加入arguments = docopt(__doc__)。
通过分析12306的网站发现请求中的站点都是站点代码,所以先通过下列代码parse_stations.py得到站点名称:站点代码的列表,
执行:python parse_stations.py > stations.py 将打印结果重定向到stations.py文件中,方便后续调用

# -*- coding: utf-8 -*-
import re
import requests
from pprint import pprint
# 此url地址可以通过分析12306页面源码得到
url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9044'
response = requests.get(url, verify=False) #利用requests发送get请求
# 此句得到的数据格式是[('北京北', 'VAP'), ('北京东', 'BOP'), ('北京', 'BJP'), ...]
# 使用正则表达式,([\u4e00-\u9fa5]+)至少一个汉字,([A-Z]+)至少一个大写字母
stations = re.findall('([\u4e00-\u9fa5]+)\|([A-Z]+)', response.text)
# 调用dict()后将格式转为字典{'北京北': 'VAP', '北京东': 'BOP', '北京': 'BJP', ...]
print(dict(stations))
完整代码如下所示:
1、由于stations中字典的key是站点名称,value是站点代码,而页面中查询结果使用的是站点代码,所以需要将此字典的key、value互换
new_stations = {v : k for k, v in stations.items()}
2、12306余票查询的响应内容的格式跟 实验楼文档中的已经不一样了,可明显看出不同字段由“|”分隔,可分析出不同字段的含义。

# -*- coding: utf-8  -*-

""" 命令行火车票查看器

Usage:
	tickets [-gdtkz] <from> <to> <date>

Options:
	-h,--help   显示帮助菜单
	-g          高铁
	-d          动车
	-t          特快
	-k          快速
	-z			直达

Example:
	tickets 北京 上海 2018-01-13
	tickets -dg 成都 南京 2018-01-13
"""

import requests
import json
from docopt import docopt
# key:站点名称 value: 站点代码
from stations import stations

# 反转k,v形成新的字典,站点代码:站点名称
new_stations = {v : k for k, v in stations.items()}

def cli():
	"""command-line interface"""
	arguments = docopt(__doc__)
	# python tickets.py -dg 合肥 天柱山 2018-01-13
    # {'-d': True,
	#'-g': True,
	# '-k': False,
	# '-t': False,
	# '-z': False,
	# '<date>': '2018-01-13',
	# '<from>': '合肥',
	# '<to>': '天柱山'}打印arguments得到一个字典
	# print(arguments)
	from_station = stations.get(arguments['<from>'])
	to_station = stations.get(arguments['<to>'])
	date = arguments['<date>']
	url = 'https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date={}&leftTicketDTO.from_station={}&leftTicketDTO.to_station={}&purpose_codes=ADULT'.format(date, from_station, to_station)

	info_list = get_train_info(url)
	print(','.join(info_list))
	# resp = requests.get(url, verify=False)
	# print(json.loads(resp.text)['data']['result'])
	# print(resp.json()['data']['result'])

def get_train_info(url):
	info_list = []

	try:
		resp = requests.get(url, verify=False)
		raw_trains = resp.json()['data']['result']

		for raw_train in raw_trains:
			data_list = raw_train.split('|')
			train_no = data_list[3]

			# 起点站
			from_station_code = data_list[6]
			from_station_name = new_stations.get(from_station_code)

            # 终点站
			to_station_code = data_list[7]
			to_station_name = new_stations.get(to_station_code)

			start_time = data_list[8]

			arrive_time = data_list[9]

			time_fucked_up = data_list[10]

			first_class_seat = data_list[31] or '--'

			second_class_seat = data_list[30] or '--'

			soft_sleeper = data_list[23] or '--'

			hard_sleeper = data_list[28] or '--'

			hard_seat = data_list[29] or '--'

			no_seat = data_list[26] or '--'

			info = '车次:{},出发站:{},目的地:{},出发时间:{},到达时间:{},历时:{},一等座:{},二等座:{},软卧:{},硬卧:{},硬座:{},无座:{}\n\n'.format(
			     train_no, from_station_name, to_station_name, start_time, arrive_time, time_fucked_up, first_class_seat,
				 second_class_seat, soft_sleeper, hard_sleeper, hard_seat, no_seat)
			info_list.append(info)

		return info_list
	except:
		return "输入信息有误,请重新输入!"


if __name__ == '__main__':
	cli()
本文介绍比较简单,可参看 实验楼文档,目前打印的形式也比较丑,还需完善。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值