build the basic frame
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,3 +1,5 @@
|
||||
.idea
|
||||
.DS_Store
|
||||
venv
|
||||
__pycache__
|
||||
env.py
|
||||
1
data/stations.txt
Executable file
1
data/stations.txt
Executable file
File diff suppressed because one or more lines are too long
72
env.py.example
Normal file
72
env.py.example
Normal file
@@ -0,0 +1,72 @@
|
||||
# encoding=utf8
|
||||
|
||||
# 12306 账号
|
||||
USER_ACCOUNTS = [
|
||||
{
|
||||
'user_name': '',
|
||||
'password': ''
|
||||
}
|
||||
]
|
||||
|
||||
# 查询任务
|
||||
QUERY_JOBS = [
|
||||
{
|
||||
'left_dates': [ # 出发日期 :Array
|
||||
"2019-01-24",
|
||||
"2019-01-25",
|
||||
"2019-01-26",
|
||||
"2019-01-27",
|
||||
"2019-01-28"
|
||||
],
|
||||
'stations': { # 车站 :Dict
|
||||
'left': '广州',
|
||||
'arrive': '达州',
|
||||
},
|
||||
'members': [
|
||||
'1'
|
||||
],
|
||||
'allow_less_member': 0,
|
||||
'seats': [ # 筛选座位 有先后顺序 :Array
|
||||
'硬卧',
|
||||
'硬座'
|
||||
],
|
||||
'train_numbers': [ # 筛选车次
|
||||
"K1096",
|
||||
"K814",
|
||||
"K356",
|
||||
"K1172",
|
||||
"K4184"
|
||||
]
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
'left_dates': [ # 出发日期 :Array
|
||||
"2019-01-24",
|
||||
"2019-01-25",
|
||||
"2019-01-26",
|
||||
"2019-01-27",
|
||||
"2019-01-28"
|
||||
],
|
||||
'stations': { # 车站 :Dict
|
||||
'left': '广州',
|
||||
'arrive': '达州',
|
||||
},
|
||||
'members': [
|
||||
'1'
|
||||
],
|
||||
'allow_less_member': 0,
|
||||
'seats': [ # 筛选座位 有先后顺序 :Array
|
||||
'硬卧',
|
||||
'硬座'
|
||||
],
|
||||
'train_numbers': [ # 筛选车次
|
||||
"K1096",
|
||||
"K814",
|
||||
"K356",
|
||||
"K1172",
|
||||
"K4184"
|
||||
]
|
||||
|
||||
}
|
||||
]
|
||||
17
main.py
Normal file
17
main.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# encoding=utf8
|
||||
|
||||
from threading import Thread
|
||||
|
||||
from py12306.log.query_log import QueryLog
|
||||
from py12306.query.query import Query
|
||||
|
||||
|
||||
def main():
|
||||
# Thread(target=Query.run).start() # 余票查询
|
||||
QueryLog.add_log('init')
|
||||
Query.run()
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
0
py12306/__init__.py
Normal file
0
py12306/__init__.py
Normal file
34
py12306/config.py
Normal file
34
py12306/config.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from os import path
|
||||
|
||||
# from py12306.helpers.config import Config
|
||||
|
||||
# 12306 账号
|
||||
USER_ACCOUNTS = []
|
||||
|
||||
# 查询任务
|
||||
QUERY_JOBS = []
|
||||
|
||||
SEAT_TYPES = {
|
||||
'商务座': 32,
|
||||
'一等座': 31,
|
||||
'二等座': 30,
|
||||
'特等座': 25,
|
||||
'软卧': 23,
|
||||
'硬卧': 28,
|
||||
'硬座': 29,
|
||||
'无座': 26,
|
||||
}
|
||||
|
||||
# Query
|
||||
QUERY_DATA_DIR = 'runtime/query'
|
||||
|
||||
|
||||
STATION_FILE = 'data/stations.txt'
|
||||
CONFIG_FILE = 'env.py'
|
||||
|
||||
if path.exists(CONFIG_FILE):
|
||||
exec(open(CONFIG_FILE, encoding='utf8').read())
|
||||
|
||||
|
||||
def get(key, default=None):
|
||||
return eval(key)
|
||||
0
py12306/helpers/__init__.py
Normal file
0
py12306/helpers/__init__.py
Normal file
360
py12306/helpers/api.py
Normal file
360
py12306/helpers/api.py
Normal file
@@ -0,0 +1,360 @@
|
||||
# coding=utf-8
|
||||
# 查询余票
|
||||
import time
|
||||
|
||||
BASE_URL_OF_12306 = 'https://kyfw.12306.cn'
|
||||
|
||||
LEFT_TICKETS = {
|
||||
"url": BASE_URL_OF_12306 + "/otn/{type}?leftTicketDTO.train_date={left_date}&leftTicketDTO.from_station={left_station}&leftTicketDTO.to_station={arrive_station}&purpose_codes=ADULT",
|
||||
"re_try": 10,
|
||||
"re_time": 0.01,
|
||||
"s_time": 0.01,
|
||||
"is_logger": False,
|
||||
"is_json": True,
|
||||
"is_cdn": True,
|
||||
}
|
||||
|
||||
urls = {
|
||||
"auth": { # 登录接口
|
||||
"req_url": "/passport/web/auth/uamtk",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"Content-Type": 1,
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"s_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"login": { # 登录接口
|
||||
"req_url": "/passport/web/login",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/login/init",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"Content-Type": 1,
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"s_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
|
||||
},
|
||||
"left_ticket_init": { # 登录接口
|
||||
"req_url": "/otn/leftTicket/init",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/login/init",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"Content-Type": 1,
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"s_time": 0.1,
|
||||
"is_logger": False,
|
||||
"is_json": False,
|
||||
|
||||
},
|
||||
"getCodeImg": { # 登录验证码
|
||||
"req_url": "/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&{0}",
|
||||
"req_type": "get",
|
||||
"Referer": "https://kyfw.12306.cn/otn/login/init",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"Content-Type": 1,
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"s_time": 0.1,
|
||||
"is_logger": False,
|
||||
"is_json": False,
|
||||
"not_decode": True,
|
||||
},
|
||||
"codeCheck": { # 验证码校验
|
||||
"req_url": "/passport/captcha/captcha-check",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/login/init",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"Content-Type": 1,
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"s_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"loginInit": { # 登录页面
|
||||
"req_url": "/otn/login/init",
|
||||
"req_type": "get",
|
||||
"Referer": "https://kyfw.12306.cn/otn/index/init",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 1,
|
||||
"re_time": 0.1,
|
||||
"s_time": 0.1,
|
||||
"is_logger": False,
|
||||
"is_json": False,
|
||||
},
|
||||
"loginInitCdn": { # 登录页面
|
||||
"req_url": "/otn/login/init",
|
||||
"req_type": "get",
|
||||
"Referer": "https://kyfw.12306.cn/otn/index/init",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 1,
|
||||
"re_time": 0.1,
|
||||
"s_time": 0.1,
|
||||
"is_logger": False,
|
||||
"is_test_cdn": True,
|
||||
"is_json": False,
|
||||
},
|
||||
"getUserInfo": { # 获取用户信息
|
||||
"req_url": "/otn/index/initMy12306",
|
||||
"req_type": "get",
|
||||
"Referer": "https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"s_time": 0.01,
|
||||
"is_logger": False,
|
||||
"is_json": False,
|
||||
},
|
||||
"userLogin": { # 用户登录
|
||||
"req_url": "/otn/login/userLogin",
|
||||
"req_type": "get",
|
||||
"Referer": "https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"s_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"uamauthclient": { # 登录
|
||||
"req_url": "/otn/uamauthclient",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"Content-Type": 1,
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"s_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"initdc_url": { # 生成订单页面
|
||||
"req_url": "/otn/confirmPassenger/initDc",
|
||||
"req_type": "get",
|
||||
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"s_time": 1,
|
||||
"is_logger": False,
|
||||
"is_json": False,
|
||||
},
|
||||
"GetJS": { # 订单页面js
|
||||
"req_url": "/otn/HttpZF/GetJS",
|
||||
"req_type": "get",
|
||||
"Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"s_time": 0.1,
|
||||
"is_logger": False,
|
||||
"is_json": False,
|
||||
},
|
||||
"odxmfwg": { # 订单页面js
|
||||
"req_url": "/otn/dynamicJs/odxmfwg",
|
||||
"req_type": "get",
|
||||
"Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"s_time": 0.1,
|
||||
"is_logger": False,
|
||||
"is_json": False,
|
||||
},
|
||||
"get_passengerDTOs": { # 获取乘车人
|
||||
"req_url": "/otn/confirmPassenger/getPassengerDTOs",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"s_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"select_url": { # 查询余票
|
||||
"req_url": "/otn/{3}?leftTicketDTO.train_date={0}&leftTicketDTO.from_station={1}&leftTicketDTO.to_station={2}&purpose_codes=ADULT",
|
||||
"req_type": "get",
|
||||
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.01,
|
||||
"s_time": 0.01,
|
||||
"is_logger": False,
|
||||
"is_json": True,
|
||||
"is_cdn": True,
|
||||
},
|
||||
"check_user_url": { # 检查用户登录
|
||||
"req_url": "/otn/login/checkUser",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.3,
|
||||
"s_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"submit_station_url": { # 提交订单
|
||||
"req_url": "/otn/leftTicket/submitOrderRequest",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.01,
|
||||
"s_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"checkOrderInfoUrl": { # 检查订单信息规范
|
||||
"req_url": "/otn/confirmPassenger/checkOrderInfo",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.01,
|
||||
"s_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"getQueueCountUrl": { # 剩余余票数
|
||||
"req_url": "/otn/confirmPassenger/getQueueCount",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.01,
|
||||
"s_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"checkQueueOrderUrl": { # 订单队列排队
|
||||
"req_url": "/otn/confirmPassenger/confirmSingleForQueue",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.01,
|
||||
"s_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"checkRandCodeAnsyn": { # 暂时没用到
|
||||
"req_url": "/otn/passcodeNew/checkRandCodeAnsyn",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.01,
|
||||
"s_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"codeImgByOrder": { # 订单页面验证码
|
||||
"req_url": "/otn/passcodeNew/getPassCodeNew?module=passenger&rand=randp&{}",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.01,
|
||||
"s_time": 0.1,
|
||||
"is_logger": False,
|
||||
"is_json": False,
|
||||
},
|
||||
"queryOrderWaitTimeUrl": { # 订单等待页面
|
||||
"req_url": "/otn/confirmPassenger/queryOrderWaitTime?random={0}&tourFlag=dc&_json_att=",
|
||||
"req_type": "get",
|
||||
"Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.01,
|
||||
"s_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"queryMyOrderNoCompleteUrl": { # 订单查询页面
|
||||
"req_url": "/otn/queryOrder/queryMyOrderNoComplete",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/queryOrder/initNoComplete",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.01,
|
||||
"s_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"initNoCompleteUrl": { # 获取订单列表
|
||||
"req_url": "/otn/queryOrder/initNoComplete",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/queryOrder/initNoComplete",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.01,
|
||||
"s_time": 0.1,
|
||||
"is_logger": False,
|
||||
"is_json": False,
|
||||
},
|
||||
"cancelNoCompleteMyOrder": { # 取消订单
|
||||
"req_url": "/otn/queryOrder/cancelNoCompleteMyOrder",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/queryOrder/initNoComplete",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.01,
|
||||
"s_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"autoSubmitOrderRequest": { # 快速自动提交订单
|
||||
"req_url": "/otn/confirmPassenger/autoSubmitOrderRequest",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"Content-Type": 1,
|
||||
"re_try": 10,
|
||||
"re_time": 0.01,
|
||||
"s_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"getQueueCountAsync": { # 快速获取订单数据
|
||||
"req_url": "/otn/confirmPassenger/getQueueCountAsync",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"Content-Type": 1,
|
||||
"re_try": 10,
|
||||
"re_time": 0.01,
|
||||
"s_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"confirmSingleForQueueAsys": { # 快速订单排队
|
||||
"req_url": "/otn/confirmPassenger/confirmSingleForQueueAsys",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
|
||||
"Content-Type": 1,
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.01,
|
||||
"s_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"cdn_host": {
|
||||
"req_url": "http://ping.chinaz.com/kyfw.12306.cn",
|
||||
"req_type": "post"
|
||||
},
|
||||
"cdn_list": {
|
||||
"req_url": "http://ping.chinaz.com/iframe.ashx?t=ping&callback=jQuery111304824429956769827_{}".format(
|
||||
int(round(time.time() * 1000))),
|
||||
"req_type": "post"
|
||||
}
|
||||
}
|
||||
14
py12306/helpers/config.py
Normal file
14
py12306/helpers/config.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# from py12306.config import get_value_by_key
|
||||
from py12306.config import get_value_by_key
|
||||
|
||||
|
||||
class BaseConfig:
|
||||
AA = 'USER_ACCOUNTS'
|
||||
|
||||
|
||||
class Config(BaseConfig):
|
||||
|
||||
@classmethod
|
||||
def get(cls, key, default=None):
|
||||
self = cls()
|
||||
return get_value_by_key(key);
|
||||
39
py12306/helpers/func.py
Normal file
39
py12306/helpers/func.py
Normal file
@@ -0,0 +1,39 @@
|
||||
from py12306 import config
|
||||
import functools
|
||||
|
||||
|
||||
def singleton(cls):
|
||||
"""
|
||||
将一个类作为单例
|
||||
来自 https://wiki.python.org/moin/PythonDecoratorLibrary#Singleton
|
||||
"""
|
||||
|
||||
cls.__new_original__ = cls.__new__
|
||||
|
||||
@functools.wraps(cls.__new__)
|
||||
def singleton_new(cls, *args, **kw):
|
||||
it = cls.__dict__.get('__it__')
|
||||
if it is not None:
|
||||
return it
|
||||
|
||||
cls.__it__ = it = cls.__new_original__(cls, *args, **kw)
|
||||
it.__init_original__(*args, **kw)
|
||||
return it
|
||||
|
||||
cls.__new__ = singleton_new
|
||||
cls.__init_original__ = cls.__init__
|
||||
cls.__init__ = object.__init__
|
||||
|
||||
return cls
|
||||
|
||||
|
||||
# 座位
|
||||
def get_seat_number_by_name(name):
|
||||
return config.SEAT_TYPES[name]
|
||||
|
||||
|
||||
def get_seat_name_by_number(number):
|
||||
return [k for k, v in config.SEAT_TYPES.items() if v == number].pop()
|
||||
|
||||
|
||||
# def test:
|
||||
34
py12306/helpers/station.py
Normal file
34
py12306/helpers/station.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from os import path
|
||||
from py12306.helpers.func import *
|
||||
|
||||
|
||||
@singleton
|
||||
class Station:
|
||||
stations = []
|
||||
|
||||
def __init__(self):
|
||||
print('Station 初始化')
|
||||
if path.exists(config.STATION_FILE):
|
||||
result = open(config.STATION_FILE, encoding='utf-8').read()
|
||||
result = result.lstrip('@').split('@')
|
||||
for i in result:
|
||||
tmp_info = i.split('|')
|
||||
self.stations.append({
|
||||
'key': tmp_info[2],
|
||||
'name': tmp_info[1],
|
||||
'pinyin': tmp_info[3],
|
||||
'id': tmp_info[5]
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def get_station_by_name(cls, name):
|
||||
self = cls()
|
||||
for station in self.stations:
|
||||
if station.get('name') == name:
|
||||
return station
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def get_station_key_by_name(cls, name):
|
||||
return cls.get_station_by_name(name).get('key')
|
||||
|
||||
0
py12306/log/__init__.py
Normal file
0
py12306/log/__init__.py
Normal file
18
py12306/log/base.py
Normal file
18
py12306/log/base.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from py12306.helpers.func import *
|
||||
|
||||
|
||||
class BaseLog:
|
||||
logs = []
|
||||
|
||||
@classmethod
|
||||
def add_log(cls, content):
|
||||
self = cls()
|
||||
self.logs.append(content)
|
||||
return self
|
||||
|
||||
@classmethod
|
||||
def flush(cls):
|
||||
self = cls()
|
||||
for i in self.logs:
|
||||
print(i)
|
||||
# print(self.logs)
|
||||
49
py12306/log/query_log.py
Normal file
49
py12306/log/query_log.py
Normal file
@@ -0,0 +1,49 @@
|
||||
import json
|
||||
from os import path
|
||||
from py12306.log.base import BaseLog
|
||||
from py12306.helpers.func import *
|
||||
|
||||
|
||||
@singleton
|
||||
class QueryLog(BaseLog):
|
||||
data = {
|
||||
'query_count': 0,
|
||||
'last_time': '',
|
||||
}
|
||||
|
||||
LOG_INIT_JOBS = ''
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.init_data()
|
||||
|
||||
def init_data(self):
|
||||
# 获取上次记录
|
||||
print('Query Log 初始化')
|
||||
file_path = config.QUERY_DATA_DIR + '/status.json'
|
||||
if path.exists(file_path):
|
||||
result = open(file_path, encoding='utf-8').read()
|
||||
if result:
|
||||
result = json.loads(result)
|
||||
self.data = {**self.data, **result}
|
||||
|
||||
@classmethod
|
||||
def print_init_jobs(cls, jobs):
|
||||
self = cls()
|
||||
"""
|
||||
输出初始化信息
|
||||
:return:
|
||||
"""
|
||||
self.add_log('# 发现任务 {} 条 #'.format(len(jobs)))
|
||||
index = 1
|
||||
for job in jobs:
|
||||
self.add_log('================== 任务 {} =================='.format(index))
|
||||
self.add_log('出发站:{} 到达站:{}'.format(job.left_station, job.arrive_station))
|
||||
self.add_log('乘车日期:{}'.format(job.left_dates))
|
||||
self.add_log('坐席:{}'.format(','.join(job.allow_seats)))
|
||||
self.add_log('乘车人:{}'.format(','.join(job.members)))
|
||||
self.add_log('筛选车次:{}'.format(','.join(job.allow_train_numbers)))
|
||||
# 乘车日期:['2019-01-24', '2019-01-25', '2019-01-26', '2019-01-27']
|
||||
index += 1
|
||||
|
||||
return self
|
||||
0
py12306/query/__init__.py
Normal file
0
py12306/query/__init__.py
Normal file
31
py12306/query/job.py
Normal file
31
py12306/query/job.py
Normal file
@@ -0,0 +1,31 @@
|
||||
from py12306.helpers.station import Station
|
||||
|
||||
|
||||
class Job:
|
||||
"""
|
||||
查询任务
|
||||
"""
|
||||
|
||||
left_dates = []
|
||||
left_station = ''
|
||||
arrive_station = ''
|
||||
left_station_code = ''
|
||||
arrive_station_code = ''
|
||||
|
||||
allow_seats = []
|
||||
allow_train_numbers = []
|
||||
members = []
|
||||
member_num = []
|
||||
|
||||
|
||||
def __init__(self, info):
|
||||
self.left_dates = info.get('left_dates')
|
||||
self.left_station = info.get('stations').get('left')
|
||||
self.arrive_station = info.get('stations').get('arrive')
|
||||
self.left_station_code = Station.get_station_key_by_name(self.left_station)
|
||||
self.arrive_station_code = Station.get_station_key_by_name(self.arrive_station)
|
||||
|
||||
self.allow_seats = info.get('seats')
|
||||
self.allow_train_numbers = info.get('train_numbers')
|
||||
self.members = info.get('members')
|
||||
self.member_num = len(self.members)
|
||||
78
py12306/query/query.py
Normal file
78
py12306/query/query.py
Normal file
@@ -0,0 +1,78 @@
|
||||
from requests_html import HTMLSession
|
||||
|
||||
import py12306.config as config
|
||||
from py12306.helpers.api import LEFT_TICKETS
|
||||
from py12306.helpers.func import *
|
||||
from py12306.helpers.station import Station
|
||||
from py12306.log.query_log import QueryLog
|
||||
from py12306.query.job import Job
|
||||
|
||||
|
||||
class Query:
|
||||
"""
|
||||
余票查询
|
||||
|
||||
"""
|
||||
jobs = []
|
||||
session = {}
|
||||
|
||||
def __init__(self):
|
||||
self.session = HTMLSession()
|
||||
|
||||
@classmethod
|
||||
def run(cls):
|
||||
self = cls()
|
||||
self.start()
|
||||
pass
|
||||
|
||||
def start(self):
|
||||
self.init_jobs()
|
||||
QueryLog.print_init_jobs(jobs=self.jobs).flush()
|
||||
for job in self.jobs:
|
||||
self.handle_single_job(job)
|
||||
|
||||
def init_jobs(self):
|
||||
jobs = config.QUERY_JOBS
|
||||
for job in jobs:
|
||||
job = Job(info=job)
|
||||
self.jobs.append(job)
|
||||
|
||||
def handle_single_job(self, job):
|
||||
"""
|
||||
处理单个任务
|
||||
根据日期循环查询
|
||||
|
||||
展示处理时间
|
||||
:param job:
|
||||
:return:
|
||||
"""
|
||||
for date in job.left_dates:
|
||||
result = self.query_by_job_and_date(job, date)
|
||||
self.handle_single_result(result)
|
||||
|
||||
station = Station.get_station_by_name('广州')
|
||||
print(station)
|
||||
pass
|
||||
|
||||
def query_by_job_and_date(self, job, date):
|
||||
"""
|
||||
通过日期进行查询
|
||||
:return:
|
||||
"""
|
||||
QueryLog.add_log('正在查询 {}, {} - {}'.format(date, job.left_station, job.arrive_station))
|
||||
url = LEFT_TICKETS.get('url').format(left_date=date, left_station=job.left_station_code,
|
||||
arrive_station=job.arrive_station_code, type='leftTicket/queryZ')
|
||||
|
||||
return self.session.get(url)
|
||||
|
||||
def handle_single_result(self, result):
|
||||
"""
|
||||
错误判断
|
||||
余票判断
|
||||
小黑屋判断
|
||||
座位判断
|
||||
乘车人判断
|
||||
:param result:
|
||||
:return:
|
||||
"""
|
||||
pass
|
||||
0
py12306/user/__init__.py
Normal file
0
py12306/user/__init__.py
Normal file
Reference in New Issue
Block a user