|
|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 bendon 于 2017-9-7 22:31 编辑
刚入门学习Python,基础教程基本过了一遍,准备写几个小项目练练手。
正好赶上买火车票出差,就想写个12306查询列车的小爬虫。在网上百度了多个版本的12306查询代码,基本都不能用了,随便找了个版本(原版地址),进行修改,具体代码如下:
- #_*_ coding:utf-8 _*_
- """命令行火车票查看器
- Usage:
- tickets [-gdtkz] <from> <to> <date>
- """
- import json
- import urllib.request
- import ssl
- from docopt import docopt
- from prettytable import PrettyTable
- from colorama import init,Fore
- from stations import stations
- ssl._create_default_https_context = ssl._create_unverified_context
- class TrainsCollection:
- header = '车次 车站 时间 历时 特等座/商务座 一等 二等 动卧 高级软卧 软卧 硬卧 软座 硬座 无座 其他'.split()
- def __init__(self, available_trains,available_place, options):
- """查询的火车班次集合
- :param available_trains: 一个列表, 包含可获得的火车班次, 每个
- 火车班次是一个字典
- :param options: 查询的选项, 如高铁, 动车, etc...
- """
- self.available_trains = available_trains
- self.available_place = available_place
- self.options = options
- @property
- def trains(self):
- for raw_train in self.available_trains:
- raw_train_list = raw_train.split('|')
- train_no = raw_train_list[3]
- initial = train_no[0].lower()
- duration = raw_train_list[10]
- if initial in self.options:
- train = [
- train_no,
- '\n'.join([Fore.LIGHTGREEN_EX + self.available_place[raw_train_list[6]] + Fore.RESET,
- Fore.LIGHTRED_EX + self.available_place[raw_train_list[7]] + Fore.RESET]),
- '\n'.join([Fore.LIGHTGREEN_EX + raw_train_list[8] + Fore.RESET,
- Fore.LIGHTRED_EX + raw_train_list[9] + Fore.RESET]),
- duration,
- raw_train_list[-4] if raw_train_list[-4] else '--',
- raw_train_list[-5] if raw_train_list[-5] else '--',
- raw_train_list[-6] if raw_train_list[-6] else '--',
- raw_train_list[-3] if raw_train_list[-3] else '--',
- raw_train_list[-15] if raw_train_list[-15] else '--',
- raw_train_list[-13] if raw_train_list[-13] else '--',
- raw_train_list[-8] if raw_train_list[-8] else '--',
- raw_train_list[-12] if raw_train_list[-12] else '--',
- raw_train_list[-7] if raw_train_list[-7] else '--',
- raw_train_list[-10] if raw_train_list[-10] else '--',
- raw_train_list[-14] if raw_train_list[-14] else '--',
- ]
- yield train
- def pretty_print(self):
- pt = PrettyTable()
- pt._set_field_names(self.header)
- for i in self.trains:
- pt.add_row(i)
- print(pt)
- def cli():
- """command-line interface"""
- arguments = docopt(__doc__)
- from_station = stations.get(arguments['<from>'])
- to_station = stations.get(arguments['<to>'])
- date = arguments['<date>']
- url = 'https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date={}&leftTicketDTO.from_station={}&leftTicketDTO.to_station={}&purpose_codes=ADULT'.format(
- date, from_station, to_station)
- req = urllib.request.Request(url)
- 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')
- html = urllib.request.urlopen(req).read()
- html = html.decode()
- dict = json.loads(html)
- available_trains = dict['data']['result']
- available_place = dict['data']['map']
- options = ''.join([
- key for key, value in arguments.items() if value is True
- ])
- TrainsCollection(available_trains, available_place, options).pretty_print()
- if __name__ == '__main__':
- cli()
复制代码
总体思路如下:
1、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)
|
|