from py12306.config import Config from py12306.cluster.cluster import Cluster from py12306.app import app_available_check from py12306.helpers.func import * from py12306.helpers.request import Request from py12306.log.query_log import QueryLog from py12306.query.job import Job from py12306.helpers.api import API_QUERY_INIT_PAGE @singleton class Query: """ 余票查询 """ jobs = [] query_jobs = [] session = {} # 查询间隔 interval = {} cluster = None is_in_thread = False retry_time = 3 is_ready = False api_type = None # Query api url, Current know value leftTicket/queryX | leftTicket/queryZ def __init__(self): self.session = Request() self.cluster = Cluster() self.update_query_interval() self.update_query_jobs() self.get_query_api_type() def update_query_interval(self, auto=False): self.interval = init_interval_by_number(Config().QUERY_INTERVAL) if auto: jobs_do(self.jobs, 'update_interval') def update_query_jobs(self, auto=False): self.query_jobs = Config().QUERY_JOBS if auto: QueryLog.add_quick_log(QueryLog.MESSAGE_JOBS_DID_CHANGED).flush() self.refresh_jobs() if not Config().is_slave(): jobs_do(self.jobs, 'check_passengers') @classmethod def run(cls): self = cls() app_available_check() self.start() pass @classmethod def check_before_run(cls): self = cls() self.init_jobs() self.is_ready = True def start(self): # return # DEBUG QueryLog.init_data() stay_second(3) # 多线程 while True: if Config().QUERY_JOB_THREAD_ENABLED: # 多线程 if not self.is_in_thread: self.is_in_thread = True create_thread_and_run(jobs=self.jobs, callback_name='run', wait=Const.IS_TEST) if Const.IS_TEST: return stay_second(self.retry_time) else: if not self.jobs: break self.is_in_thread = False jobs_do(self.jobs, 'run') if Const.IS_TEST: return # while True: # app_available_check() # if Config().QUERY_JOB_THREAD_ENABLED: # 多线程 # create_thread_and_run(jobs=self.jobs, callback_name='run') # else: # for job in self.jobs: job.run() # if Const.IS_TEST: return # self.refresh_jobs() # 刷新任务 def refresh_jobs(self): """ 更新任务 :return: """ allow_jobs = [] for job in self.query_jobs: id = md5(job) job_ins = objects_find_object_by_key_value(self.jobs, 'id', id) # [1 ,2] if not job_ins: job_ins = self.init_job(job) if Config().QUERY_JOB_THREAD_ENABLED: # 多线程重新添加 create_thread_and_run(jobs=job_ins, callback_name='run', wait=Const.IS_TEST) allow_jobs.append(job_ins) for job in self.jobs: # 退出已删除 Job if job not in allow_jobs: job.destroy() QueryLog.print_init_jobs(jobs=self.jobs) def init_jobs(self): for job in self.query_jobs: self.init_job(job) QueryLog.print_init_jobs(jobs=self.jobs) def init_job(self, job): job = Job(info=job, query=self) self.jobs.append(job) return job @classmethod def wait_for_ready(cls): self = cls() if self.is_ready: return self stay_second(self.retry_time) return self.wait_for_ready() @classmethod def job_by_name(cls, name) -> Job: self = cls() for job in self.jobs: if job.job_name == name: return job return None @classmethod def job_by_name(cls, name) -> Job: self = cls() return objects_find_object_by_key_value(self.jobs, 'job_name', name) @classmethod def job_by_account_key(cls, account_key) -> Job: self = cls() return objects_find_object_by_key_value(self.jobs, 'account_key', account_key) @classmethod def get_query_api_type(cls): import re self = cls() if self.api_type: return self.api_type response = self.session.get(API_QUERY_INIT_PAGE) if response.status_code == 200: res = re.search(r'var CLeftTicketUrl = \'(.*)\';', response.text) try: self.api_type = res.group(1) except IndexError: pass return cls.get_query_api_type() # def get_jobs_from_cluster(self): # jobs = self.cluster.session.get_dict(Cluster.KEY_JOBS) # return jobs # # def update_jobs_of_cluster(self): # if config.CLUSTER_ENABLED and config.NODE_IS_MASTER: # return self.cluster.session.set_dict(Cluster.KEY_JOBS, self.query_jobs) # # def refresh_jobs(self): # if not config.CLUSTER_ENABLED: return # jobs = self.get_jobs_from_cluster() # if jobs != self.query_jobs: # self.jobs = [] # self.query_jobs = jobs # QueryLog.add_quick_log(QueryLog.MESSAGE_JOBS_DID_CHANGED).flush() # self.init_jobs()