tickts.py:
#tickts.py
#2018-01-22
#python 3.4 Eclipse IDE
from splinter.browser import Browser
from time import sleep
import traceback
import time
import sys
import requests
import re
import json
from pprint import pprint
from prettytable import PrettyTable
from docopt import docopt
from train import TrainCollection #train為 train.py 中的class:TrainCollection 的引用
from houcedu import huoche #huocedu為huocedu.py中的class: huoche 的引用
from stations import stations
#pip install traceback2
#pip install linecache2
#pip install splinter windows xp python 3.4
#pip install PrettyTable
#pip install docopt
#pip install r2
#pip install colorama
# https://github.com/python/cpython/tree/3.6/Lib
#b = Browser(driver_name="Chrome")
#url ="https://kyfw.12306.cn/otn/leftTicket/init"
#b = Browser(driver_name="Chrome")
#b.visit(url)
cities= {'成都':'%u6210%u90FD%2CCDW',
'重庆':'%u91CD%u5E86%2CCQW',
'北京':'%u5317%u4EAC%2CBJP',
'广州':'%u5E7F%u5DDE%2CGZQ',
'杭州':'%u676D%u5DDE%2CHZH',
'宜昌':'%u5B9C%u660C%2CYCN',
'郑州':'%u90D1%u5DDE%2CZZF',
'深圳':'%u6DF1%u5733%2CSZQ',
'西安':'%u897F%u5B89%2CXAY',
'大连':'%u5927%u8FDE%2CDLT',
'武汉':'%u6B66%u6C49%2CWHN',
'上海':'%u4E0A%u6D77%2CSHH',
'南京':'%u5357%u4EAC%2CNJH',
'合肥':'%u5408%u80A5%2CHFH'}
#if __name__ == '__main__':
huoche=huoche()
print(cities.get('成都'))
huoche.starts=cities.get('成都')
huoche.ends = cities.get('杭州')
huoche.dtime = '2018-01-05'
#huoche.start() #未有權限
#https://kyfw.12306.cn/otn/lcxxcx/query?purpose_codes=ADULT&queryDate=2016-07-01&from_station=SHH&to_station=BJP 拒絕訪問
# pprint: 格式化输出
url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.8971'
#获取URL
response = requests.get(url, verify=False)
#正则提取中文字母和代号
stations = re.findall(u'([\u4e00-\u9fa5]+)\|([A-Z]+)', response.text)
# indent:定义打印信息的缩进为4个空格
#pprint(dict(stations), indent=4)
# 拼音輸出
url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.8955'
texts = requests.get(url, verify=False)
stations = re.findall(u'([A-Z]+)\|([a-z]+)', texts.text)
stations = dict(stations)
stations = dict(zip(stations.values(), stations.keys()))
#pprint(stations, indent=4)
#
def cli():
arguments = docopt(__doc__)
from_staion = stations.get(arguments['<from>'])
to_station = stations.get(arguments['<to>'])
date = arguments['<date>']
# 构建URL
url = 'https://kyfw.12306.cn/otn/lcxxcx/query?purpose_codes=ADULT&queryDate={}&from_station={}&to_station={}'.format(
date, from_staion, to_station
)
def clis():
# 添加verify=False参数不验证证书
r = requests.get(url, verify=False)
print(r.json())
def clid():
arguments = docopt(__doc__)
from_staion = stations.get(arguments['<from>'])
to_station = stations.get(arguments['<to>'])
date = arguments['<date>']
# 构建URL
url = 'https://kyfw.12306.cn/otn/lcxxcx/query?purpose_codes=ADULT&queryDate={}&from_station={}&to_station={}'.format(
date, from_staion, to_station
)
r = requests.get(url, verify=False)
rows = r.json()['data']['datas']
trains = TrainCollection(rows)
trains.pretty_print()
train.py:
#train.py
#2018-01-22
import time
import sys
import requests
import re
from pprint import pprint
from prettytable import PrettyTable
class TrainCollection(object):
"""
解析列车信息
"""
# 显示车次、出发/到达站、 出发/到达时间、历时、一等坐、二等坐、软卧、硬卧、硬座
header = '序号 车次 出发站/到达站 出发时间/到达时间 历时 商务座 一等座 二等座 软卧 硬卧 硬座 无座'.split()
def __init__(self,rows,traintypes):
self.rows = rows
self.traintypes = traintypes
def _get_duration(self,row):
"""
获取车次运行的时间
"""
duration = row.get('lishi').replace(':','小时') + '分'
if duration.startswith('00'):
return duration[4:]
elif duration.startswith('0'):
return duration[1:]
return duration
@property
def trains(self):
result = []
flag = 0
for row in self.rows:
if row['station_train_code'][0] in self.traintypes:
flag += 1
train = [
# 序号
flag,
# 车次
row['station_train_code'],
# 出发、到达站点
'/'.join([row['from_station_name'],row['to_station_name']]),
# 成功、到达时间
'/'.join([row['start_time'],row['arrive_time']]),
# duration 时间
self._get_duration(row),
# 商务座
row['swz_num'],
# 一等座
row['zy_num'],
# 二等座
row['ze_num'],
# 软卧
row['rw_num'],
# 硬卧
row['yw_num'],
# 硬座
row['yz_num'],
# 无座
row['wz_num']
]
result.append(train)
return result
def print_pretty(self):
"""打印列车信息"""
pt = PrettyTable()
pt._set_field_names(self.header)
for train in self.trains:
pt.add_row(train)
print(pt)
houcedu.py:
#houcedu.py
#2018-01-22
from splinter.browser import Browser
from time import sleep
import traceback
import time
import sys
import requests
import re
class huoche(object):
"""docstring for huoche"""
driver_name=''
executable_path=''
#用户名,密码
username = u"geovindu"
passwd = u"888888"
# cookies值得自己去找, 下面两个分别是上海, 太原南
starts = u"%u4E0A%u6D77%2CSHH"
ends = u"%u592A%u539F%2CTYV"
# 时间格式2018-01-19
dtime = u"2018-01-19"
# 车次,选择第几趟,0则从上之下依次点击
order = 0
###乘客名
users = [u"你的名字"]
##席位
xb = u"二等座"
pz=u"成人票"
"""网址"""
ticket_url = "https://kyfw.12306.cn/otn/leftTicket/init"
login_url = "https://kyfw.12306.cn/otn/login/init"
initmy_url = "https://kyfw.12306.cn/otn/index/initMy12306"
buy="https://kyfw.12306.cn/otn/confirmPassenger/initDc"
login_url='https://kyfw.12306.cn/otn/login/init'
def __init__(self):
self.driver_name='chrome'
self.executable_path='/usr/local/bin/chromedriver'
def login(self):
self.driver.visit(self.login_url)
# 填充密码
self.driver.fill("loginUserDTO.user_name", self.username)
# sleep(1)
self.driver.fill("userDTO.password", self.passwd)
print (u"等待验证码,自行输入...")
while True:
if self.driver.url != self.initmy_url:
sleep(1)
else:
break
def start(self):
self.driver=Browser(driver_name=self.driver_name,executable_path=self.executable_path)
self.driver.driver.set_window_size(1400, 1000)
self.login()
# sleep(1)
self.driver.visit(self.ticket_url)
try:
print (u"购票页面开始...")
# sleep(1)
# 加载查询信息
self.driver.cookies.add({"_jc_save_fromStation": self.starts})
self.driver.cookies.add({"_jc_save_toStation": self.ends})
self.driver.cookies.add({"_jc_save_fromDate": self.dtime})
self.driver.reload()
count=0
if self.order!=0:
while self.driver.url==self.ticket_url:
self.driver.find_by_text(u"查询").click()
count += 1
print (u"循环点击查询... 第 %s 次" % count)
# sleep(1)
try:
self.driver.find_by_text(u"预订")[self.order - 1].click()
except Exception as e:
print (e)
print (u"还没开始预订")
continue
else:
while self.driver.url == self.ticket_url:
self.driver.find_by_text(u"查询").click()
count += 1
print (u"循环点击查询... 第 %s 次" % count)
# sleep(0.8)
try:
for i in self.driver.find_by_text(u"预订"):
i.click()
sleep(1)
except Exception as e:
print (e)
print (u"还没开始预订 %s" %count)
continue
print (u"开始预订...")
# sleep(3)
# self.driver.reload()
sleep(1)
print (u'开始选择用户...')
for user in self.users:
self.driver.find_by_text(user).last.click()
print (u"提交订单...")
sleep(1)
# self.driver.find_by_text(self.pz).click()
# self.driver.find_by_id('').select(self.pz)
# # sleep(1)
# self.driver.find_by_text(self.xb).click()
# sleep(1)
self.driver.find_by_id('submitOrder_id').click()
# print u"开始选座..."
# self.driver.find_by_id('1D').last.click()
# self.driver.find_by_id('1F').last.click()
sleep(1.5)
print (u"确认选座...")
self.driver.find_by_id('qr_submit_id').click()
except Exception as e:
print (e)
parse_station.py:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# __Author__: hong
# parse_station.py
import re
import requests
from pprint import pprint
# pprint: 格式化输出
#url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.8971'
#获取URL
#response = requests.get(url, verify=False)
#正则提取中文字母和代号
#stations = re.findall(u'([\u4e00-\u9fa5]+)\|([A-Z]+)', response.text)
# indent:定义打印信息的缩进为4个空格
#pprint(dict(stations), indent=4)
url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.8955'
texts = requests.get(url, verify=False)
stations = re.findall(r'([A-Z]+)\|([a-z]+)', texts.text)
stations = dict(stations)
stations = dict(zip(stations.values(), stations.keys()))
pprint(stations, indent=4)
stations.py
#coding=utf-8
# stations.py
import requests
import re
from pprint import pprint
stations={ 'abagaqi': 'AQC',
'acheng': 'ACB',
'aershan': 'ART',
'aershanbei': 'ARX',
'aihe': 'AHP',
'aijiacun': 'AJJ',
'ajin': 'AJD',
'akesu': 'ASR',
'aketao': 'AER',
'alashankou': 'AKR',
'aletai': 'AUR',
'alihe': 'AHX',
'alongshan': 'ASX',
'amuer': 'JTX',
'ananzhuang': 'AZM',
'anda': 'ADX',
'ande': 'ARW',
'anding': 'ADP',
'anduo': 'ADO',
'angangxi': 'AAX',
'anguang': 'AGT',
'anhua': 'PKQ',
'anjia': 'AJB',
'anjing': 'PYW',
'ankang': 'AKY',
'ankouyao': 'AYY',
'anlong': 'AUZ',
'anlu': 'ALN',
'anping': 'APT',
'anqing': 'AQH',
'anqingxi': 'APH',
'anren': 'ARG',
'anshan': 'AST',
'anshanxi': 'AXT',
'anshun': 'ASW',
'anshunxi': 'ASE',
'antang': 'ATV',
'antingbei': 'ASH',
'antu': 'ATL',
'antuxi': 'AXL',
'anxi': 'AXS',
'anyang': 'AYF',
'anyangdong': 'ADF',
'aohan': 'YED',
'aojiang': 'ARH',
'aolibugao': 'ALD',
'atushi': 'ATR',
'babu': 'BBE',
'bachu': 'BCR',
'badaling': 'ILP',
'badong': 'BNN',
'bafangshan': 'FGQ',
'baibiguan': 'BGV',
'baicheng': 'BCT',
'baigou': 'FEP',
'baiguo': 'BGM',
'baihe': 'BEL',
'baihedong': 'BIY',
'baihexian': 'BEY',
'baijian': 'BAP',
'baijigou': 'BJJ',
'baijipo': 'BBM',
'baikuipu': 'BKB',
'bailang': 'BAT',
'bailixia': 'AAP',
'baimajing': 'BFQ',
'baiqi': 'BQP',
'baiquan': 'BQL',
'baise': 'BIZ',
'baishanshi': 'HJL',
'baishapo': 'BPM',
'baishapu': 'BSN',
'baishishan': 'BAL',
'baishuijiang': 'BSY',
'baishuixian': 'BGY',
'baishuizhen': 'BUM',
'baiyangdian': 'FWP',
'baiyi': 'FHW',
'baiyinchagan': 'BYC',
'baiyinhuanan': 'FNC',
'baiyinhushuo': 'BCD',
'baiyinshi': 'BNJ',
'baiyintala': 'BID',
'baiyinxi': 'BXJ',
'baiyunebo': 'BEC',
'bajiaotai': 'BTD',
'balin': 'BLX',
'bamiancheng': 'BMD',
'bamiantong': 'BMB',
'bancheng': 'BUP',
'banmaoqing': 'BNM',
'bantang': 'NGQ',
'bantian': 'BTQ',
'baodi': 'BPP',
'baoding': 'BDP',
'baodingdong': 'BMP',
'baohuashan': 'BWH',
'baoji': 'BJY',
'baojinan': 'BBY',
'baokang': 'BKD',
'baolage': 'BQC',
'baolin': 'BNB',
'baolongshan': 'BND',
'baoqing': 'BUB',
'baoquanling': 'BQB',
'baotou': 'BTC',
'baotoudong': 'FDC',
'bashan': 'BAY',
'baxiantong': 'VXD',
'bayangaole': 'BAC',
'bayuquan': 'BYT',
'bazhong': 'IEW',
'bazhongdong': 'BDE',
'bazhou': 'RMP',
'bazhouxi': 'FOP',
'beian': 'BAB',
'beibei': 'BPW',
'beidaihe': 'BEP',
'beihai': 'BHZ',
'beijiao': 'IBQ',
'beijing': 'BJP',
'beijingbei': 'VAP',
'beijingdong': 'BOP',
'beijingnan': 'VNP',
'beijingxi': 'BXP',
'beijingzi': 'BRT',
'beiliu': 'BOZ',
'beimaquanzi': 'BRP',
'beipiaonan': 'RPD',
'beitai': 'BTT',
'beitun': 'BYP',
'beitunshi': 'BXR',
'beiying': 'BIV',
'beiyinhe': 'BYB',
'beizhai': 'BVP',
'bencha': 'FWH',
'bengbu': 'BBH',
'bengbunan': 'BMH',
'benhong': 'BVC',
'benxi': 'BXT',
'benxihu': 'BHT',
'benxixincheng': 'BVT',
'bijiang': 'BLQ',
'bijiashan': 'BSB',
'bijiguan': 'BJM',
'binhai': 'FHP',
'binhaibei': 'FCP',
'binjiang': 'BJB',
'binxian': 'BXY',
'binyang': 'UKZ',
'binzhou': 'BIK',
'bishan': 'FZW',
'boao': 'BWQ',
'bobai': 'BBZ',
'boketu': 'BKX',
'bole': 'BOR',
'boli': 'BLB',
'botou': 'BZP',
'boxing': 'BXK',
'bozhou': 'BZH',
'buhai': 'BUT',
'buliekai': 'BLR',
'caijiagou': 'CJT',
'caijiapo': 'CJY',
'caishan': 'CON',
'cangnan': 'CEH',
'cangshi': 'CST',
'cangxi': 'CXE',
'cangzhou': 'COP',
'cangzhouxi': 'CBP',
'caohai': 'WBW',
'caohekou': 'CKT',
'caoshi': 'CSL',
'caoxian': 'CXK',
'caozili': 'CFP',
'ceheng': 'CHZ',
'cenxi': 'CNZ',
'chabuga': 'CBC',
'chaganhu': 'VAT',
'chaigang': 'CGT',
'chaigoupu': 'CGV',
'chaihe': 'CHB',
'chajiang': 'CAM',
'chaka': 'CVO',
'chaling': 'CDG',
'chalingnan': 'CNG',
'changcheng': 'CEJ',
'changchong': 'CCM',
'changchun': 'CCT',
'changchunnan': 'CET',
'changchunxi': 'CRT',
'changde': 'VGQ',
'changdian': 'CDT',
'changge': 'CEF',
'changle': 'CLK',
'changli': 'CLP',
'changlingzi': 'CLT',
'changlinhe': 'FVH',
'changnong': 'CNJ',
'changping': 'DAQ',
'changpingbei': 'VBP',
'changpingdong': 'FQQ',
'changpingnan': 'FPQ',
'changpoling': 'CPM',
'changqingqiao': 'CQJ',
'changsha': 'CSQ',
'changshan': 'CSU',
'changshanan': 'CWQ',
'changshantun': 'CVT',
'changshaxi': 'RXQ',
'changshou': 'EFW',
'changshoubei': 'COW',
'changshouhu': 'CSE',
'changting': 'CES',
'changtingnan': 'CNS',
'changtingzhen': 'CDB',
'changtu': 'CTT',
'changtuxi': 'CPT',
'changwu': 'CWY',
'changxing': 'CBH',
'changxingnan': 'CFH',
'changyang': 'CYN',
'changyuan': 'CYF',
'changzheng': 'CZJ',
'changzhi': 'CZF',
'changzhibei': 'CBF',
'changzhou': 'CZH',
'changzhoubei': 'ESH',
'changzhuang': 'CVK',
'chaohu': 'CIH',
'chaohudong': 'GUH',
'chaolianggou': 'CYP',
'chaoshan': 'CBQ',
'chaotian': 'CTE',
'chaoyang': 'CNQ',
'chaoyangchuan': 'CYL',
'chaoyangdi': 'CDD',
'chaoyangnan': 'CYD',
'chaoyangzhen': 'CZL',
'chaozhou': 'CKQ',
'chasuqi': 'CSC',
'chengcheng': 'CUY',
'chengde': 'CDP',
'chengdedong': 'CCP',
'chengdu': 'CDW',
'chengdudong': 'ICW',
'chengdunan': 'CNW',
'chenggaozi': 'CZB',
'chenggu': 'CGY',
'chenggubei': 'CBY',
'chengjisihan': 'CJX',
'chenguanying': 'CAJ',
'chengyang': 'CEK',
'chengzitan': 'CWT',
'chenming': 'CMB',
'chenqing': 'CQB',
'chenxi': 'CXQ',
'chenxiangtun': 'CXT',
'chenzhou': 'CZQ',
'chenzhouxi': 'ICQ',
'chezhuanwan': 'CWM',
'chibi': 'CBN',
'chibibei': 'CIN',
'chifeng': 'CFD',
'chifengxi': 'CID',
'chizhou': 'IYH',
'chongqing': 'CQW',
'chongqingbei': 'CUW',
'chongqingnan': 'CRW',
'chongqingxi': 'CXW',
'chongren': 'CRG',
'chongzuo': 'CZZ',
'chuangyecun': 'CEX',
'chunwan': 'CQQ',
'chunyang': 'CAL',
'chushan': 'CSB',
'chuxiongnan': 'COM',
'chuzhou': 'CXH',
'chuzhoubei': 'CUH',
'cili': 'CUQ',
'cishan': 'CSP',
'cixi': 'CRP',
'cixian': 'CIP',
'ciyao': 'CYK',
'congjiang': 'KNW',
'cuihuangkou': 'CHP',
'cuogang': 'CAX',
'daan': 'RAT',
'daanbei': 'RNT',
'daba': 'DBJ',
'daban': 'DBC',
'dachaigou': 'DGJ',
'dacheng': 'DCT',
'dadenggou': 'DKJ',
'dafangnan': &#