def execute(self): url = "https://kyfw.12306.cn/otn/leftTicket/query" params = self.__get_query_params() json = webrequest.get_json(url, params=params) try: json_data = json["data"] except RequestError as ex: if ex.args[0] == "选择的查询日期不在预售日期范围内": raise DateOutOfRangeError() from ex raise logger.debug("Got train list from {0} to {1} on {2}".format( self.departure_station.name, self.destination_station.name, timeconverter.date_to_str(self.date))) train_list = [] station_list = StationList.instance() for train_data in json_data: query_data = train_data["queryLeftNewDTO"] departure_station = station_list.get_by_id(query_data["from_station_telecode"]) destination_station = station_list.get_by_id(query_data["to_station_telecode"]) if self.exact_departure_station and departure_station != self.departure_station: continue if self.exact_destination_station and destination_station != self.destination_station: continue train = Train(train_data, departure_station, destination_station, self.pricing, self.date) train_list.append(train) return train_list
def __get_query_params(self): return [ ("leftTicketDTO.train_date", timeconverter.date_to_str(self.date)), ("leftTicketDTO.from_station", self.departure_station.id), ("leftTicketDTO.to_station", self.destination_station.id), ("purpose_codes", TicketPricing.SEARCH_LOOKUP[self.pricing]) ]
def __get_query_params(self): return [ ("leftTicketDTO.train_date", timeconverter.date_to_str(self.date)), ("leftTicketDTO.from_station", self.departure_station.id), ("leftTicketDTO.to_station", self.destination_station.id), ("purpose_codes", "ADULT"), ("randCode", self.captcha.answer) ]
def __get_price_query_params(self): return [ ("train_no", self.id), ("from_station_no", self.departure_index), ("to_station_no", self.destination_index), ("seat_types", self.data["seat_types"]), ("train_date", timeconverter.date_to_str(self.departure_time)) ]
def __get_train_data_query_params(train): return [ ("train_no", train.id), ("from_station_telecode", train.departure_station.id), ("to_station_telecode", train.destination_station.id), # Apparently you're not supposed to use the actual # train date here, not the date returned in the # train query data. And yes, they can be different. ("depart_date", timeconverter.date_to_str(train.data["alt_date"]).strftime("%Y%m%d")) ]
def select_train_date(auto): invalid_date_printer = lambda ex: localization.INVALID_DATE.format( timeconverter.date_to_str(datetime.datetime.now()) ) return prompt_value_use_config( prompt=localization.ENTER_DATE, input_parser=timeconverter.str_to_date, error_handler=invalid_date_printer, config_key=auto and "date" )
def query(station_list, retry, auto): # Construct query object query_obj = TrainQuery() query_obj.date = select_train_date(auto) query_obj.departure_station = select_departure_station(station_list, auto) query_obj.destination_station = select_destination_station(station_list, auto) query_obj.exact_departure_station = config.get("exact_departure_station", False) query_obj.exact_destination_station = config.get("exact_destination_station", False) filter_obj = create_train_filters() sorter_obj = create_train_sorters() custom_filter = config.get("custom_filter") custom_sorter = config.get("custom_sorter") sleep_time = config.get("search_retry_rate", 1) while True: try: # Get raw train list train_list = query_obj.execute() except DateOutOfRangeError: # Invalid date provided, prompt the user for a new one print(localization.DATE_OUT_OF_RANGE.format(timeconverter.date_to_str(query_obj.date))) # Forcibly disable auto mode, to avoid re-using an # invalid date again query_obj.date = select_train_date(False) continue # Now we filter the resulting list original_count = len(train_list) train_list = filter_obj.filter(train_list) if custom_filter is not None: custom_filter(train_list) filtered_count = len(train_list) # Make sure there's at least one train if filtered_count == 0: if original_count > 0: print(localization.ALL_TRAINS_FILTERED.format(original_count)) if retry: print(localization.RETRYING_SEARCH.format(sleep_time)) time.sleep(sleep_time) continue else: return None else: print(localization.NO_TRAINS_FOUND) return None # After filtering the trains, we sort the list sorter_obj.sort(train_list) if custom_sorter is not None: custom_sorter(train_list) return train_list
def __get_query_params(self): return [ ("leftTicketDTO.train_no", self.__data__[self.date][self.train_name]), ("leftTicketDTO.train_date", timeconverter.date_to_str(self.date)), ("rand_code", self.captcha.answer) ]