鱼C论坛

 找回密码
 立即注册
查看: 2576|回复: 2

12306余票查询输出无结果的疑问

[复制链接]
发表于 2017-9-7 22:25:42 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 bendon 于 2017-9-7 22:31 编辑

刚入门学习Python,基础教程基本过了一遍,准备写几个小项目练练手。
正好赶上买火车票出差,就想写个12306查询列车的小爬虫。在网上百度了多个版本的12306查询代码,基本都不能用了,随便找了个版本(原版地址),进行修改,具体代码如下:
  1. #_*_ coding:utf-8 _*_

  2. """命令行火车票查看器
  3. Usage:
  4.         tickets [-gdtkz] <from> <to> <date>
  5. """


  6. import json
  7. import urllib.request
  8. import ssl
  9. from docopt import docopt
  10. from prettytable import PrettyTable
  11. from colorama import init,Fore

  12. from stations import stations



  13. ssl._create_default_https_context = ssl._create_unverified_context

  14. class TrainsCollection:
  15.     header = '车次 车站 时间 历时 特等座/商务座 一等 二等 动卧 高级软卧 软卧 硬卧 软座 硬座 无座 其他'.split()

  16.     def __init__(self, available_trains,available_place, options):
  17.         """查询的火车班次集合
  18.         :param available_trains: 一个列表, 包含可获得的火车班次, 每个
  19.                                  火车班次是一个字典
  20.         :param options: 查询的选项, 如高铁, 动车, etc...
  21.         """
  22.         self.available_trains = available_trains
  23.         self.available_place = available_place
  24.         self.options = options

  25.     @property
  26.     def trains(self):
  27.         for raw_train in self.available_trains:
  28.             raw_train_list = raw_train.split('|')
  29.             train_no = raw_train_list[3]
  30.             initial = train_no[0].lower()
  31.             duration = raw_train_list[10]
  32.             if initial in self.options:
  33.                 train = [
  34.                     train_no,
  35.                     '\n'.join([Fore.LIGHTGREEN_EX + self.available_place[raw_train_list[6]] + Fore.RESET,
  36.                             Fore.LIGHTRED_EX + self.available_place[raw_train_list[7]] + Fore.RESET]),
  37.                     '\n'.join([Fore.LIGHTGREEN_EX + raw_train_list[8] + Fore.RESET,
  38.                            Fore.LIGHTRED_EX + raw_train_list[9] + Fore.RESET]),
  39.                     duration,
  40.                     raw_train_list[-4] if raw_train_list[-4] else '--',
  41.                     raw_train_list[-5] if raw_train_list[-5] else '--',
  42.                     raw_train_list[-6] if raw_train_list[-6] else '--',
  43.                     raw_train_list[-3] if raw_train_list[-3] else '--',
  44.                     raw_train_list[-15] if raw_train_list[-15] else '--',
  45.                     raw_train_list[-13] if raw_train_list[-13] else '--',
  46.                     raw_train_list[-8] if raw_train_list[-8] else '--',
  47.                     raw_train_list[-12] if raw_train_list[-12] else '--',
  48.                     raw_train_list[-7] if raw_train_list[-7] else '--',
  49.                     raw_train_list[-10] if raw_train_list[-10] else '--',
  50.                     raw_train_list[-14] if raw_train_list[-14] else '--',
  51.                 ]
  52.                 yield train


  53.     def pretty_print(self):
  54.         pt = PrettyTable()
  55.         pt._set_field_names(self.header)
  56.         for i in self.trains:
  57.             pt.add_row(i)
  58.         print(pt)



  59. def cli():
  60.     """command-line interface"""
  61.     arguments = docopt(__doc__)
  62.     from_station = stations.get(arguments['<from>'])
  63.     to_station = stations.get(arguments['<to>'])
  64.     date = arguments['<date>']

  65.     url = 'https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date={}&leftTicketDTO.from_station={}&leftTicketDTO.to_station={}&purpose_codes=ADULT'.format(
  66.         date, from_station, to_station)
  67.     req = urllib.request.Request(url)
  68.     req.add_header('User-Agent','Mozilla/5.0(Windows NT 10.0;Win64;x64)AppleWebKit/537.36(KHTML, like Gecko)Chrome/59.0.3071.115 Safari/537.36')
  69.     html = urllib.request.urlopen(req).read()
  70.     html = html.decode()
  71.     dict = json.loads(html)
  72.     available_trains = dict['data']['result']
  73.     available_place = dict['data']['map']
  74.     options = ''.join([
  75.         key for key, value in arguments.items() if value is True
  76.     ])
  77.     TrainsCollection(available_trains, available_place, options).pretty_print()





  78. if __name__ == '__main__':
  79.     cli()
复制代码


总体思路如下:
1、12306查询页面代码分析:找到关键字

12306查询

12306查询

from_station
to_station
train_date
2、从抓包数据中获取到该请求的url:https://kyfw.12306.cn/otn/leftTi ... purpose_codes=ADULT

3、返回的数据是json格式,利用Python进行解析转换

4、利用prettytable进行输出



疑问一:
是不是json解析方法不准确或不到位,查询不定时出现错误:

错误提示

错误提示


疑问二:

对    @property的所起的作用不是很明白

疑问三:

最终错误出在哪里?为什么没有PT没有数据

输出结果

输出结果



stations.py文件:(下载后修改后缀名为PY
stations.rar (60.74 KB, 下载次数: 11)



小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2018-1-8 16:56:53 | 显示全部楼层
楼主解决问题了吗?我也卡在这里了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-1-9 20:45:22 From FishC Mobile | 显示全部楼层
http://bbs.fishc.com/forum.php?mod=viewthread&tid=102851&extra=page%3D1&mobile=2我今天刚发的。。。不懂可以私信我
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-12-23 19:39

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表