Beispiel #1
0
 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
Beispiel #2
0
 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])
     ]
Beispiel #3
0
 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)
     ]
Beispiel #4
0
 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))
     ]
Beispiel #5
0
 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"))
     ]
Beispiel #6
0
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"
    )
Beispiel #7
0
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
Beispiel #8
0
 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)
     ]