def main(): """ メインルーチン """ # 祝日の初期化 public_holiday = [[], [], [], [], [], [], [], [], [], [], [], [], []] # 送信メッセージリストの初期化 message_bodies = [] # 処理の開始 # 空き予約リストの初期化 reserves_list = {} # 祝日設定ファイルを読み込んで、祝日リストを作成する reserve_tools.set_public_holiday('public_holiday.json', public_holiday) # 設定ファイルを読み込んで、設定パラメータをセットする cfg = reserve_tools.read_json_cfg('cfg.json') # ロギングを設定する logger = reserve_tools.mylogger(cfg) # 検索リストを作成する target_months_list = reserve_tools.create_month_list(cfg, logger=logger) #datetime_list = create_datetime_list(target_months_list, public_holiday, cfg) date_list = reserve_tools.create_date_list_chofu(target_months_list, public_holiday, cfg) target_year_month_list = reserve_tools.create_year_month_list( target_months_list) logger.info(f'target_year_month_list: {target_year_month_list}') # 空き予約ページにアクセスし、cookieを取得する (cookies, response) = get_cookie(cfg) # 検索方法選択ページ、施設リストページにアクセスする (response, pre_url) = go_to_search_menu(cfg, cookies, response, logger=logger) # 空き予約検索を開始する reserves_list = get_reserves(cfg, target_year_month_list, date_list, reserves_list, cookies, response, pre_url, logger=logger) logger.info(json.dumps(reserves_list, indent=2, ensure_ascii=False)) # LINEにメッセージを送信する ## メッセージ本体を作成する message_bodies = reserve_tools.create_message_body(reserves_list, message_bodies, cfg, logger=logger) ## LINEに空き予約情報を送信する reserve_tools.send_line_notify(message_bodies, cfg, logger=logger) #exit() return logger
def postproc_search_empty_reserves(cfg, threadsafe_list, logger=None): """ 空き予約リストを整形して、LINEに通知する """ # 空き予約結果リストの通知メッセージ文の作成 # 空き予約結果リストのLINE通知 # 送信メッセージリストの初期化 message_bodies = [] ## メッセージ本体を作成する reserve_tools.create_message_body(threadsafe_list.reserves_list, message_bodies, cfg, logger=logger) ## LINEに空き予約情報を送信する reserve_tools.send_line_notify(message_bodies, cfg, logger=logger) return None
def main_reserve_proc(cfg, logger, reserves_list, target_months_list, public_holiday, headers): """ 予約処理のメインルーチン """ # 全体で予約できた件数 whole_reserved_num = 0 # 1回の予約処理の全体の最大予約件数 max_whole_reserved_num = cfg['whole_reserved_limit_at_onetime'] # ユーザー毎の既存予約件数を含めた最大件数 max_user_reserved_num = cfg['reserved_limit'] # 1回の予約処理のユーザー毎の最大予約件数 max_user_reserved_num_at_onetime = cfg['user_reserved_limit_at_onetime'] # 空き予約リストに値があるかないかを判断し、予約処理を開始する if len(reserves_list) == 0: logger.info(f'stop do reserve because no empty reserve.') return logger # 予約希望日リストを作成する want_date_list = reserve_tools.create_want_date_list(target_months_list, public_holiday, cfg, logger=logger) logger.debug(f'want_date_list: {want_date_list}') # 希望時間帯を取得する want_hour_list = cfg['want_hour_list'] # 希望施設名を取得する want_location_list = cfg['want_location_list'] # 予約処理対象の希望日、希望時間帯のリストを作成する # 空き予約リストを昇順にソートする sorted_reserves_list = reserve_tools.sort_reserves_list(reserves_list) # 空き予約リストから、空き予約日と時間帯を取得する target_reserves_list = reserve_tools.create_target_reserves_list_hachioji( sorted_reserves_list, want_date_list, want_hour_list, want_location_list, logger=logger) # 希望日+希望時間帯+希望コートのDictを出力する logger.info(f'target_reserves_list: {target_reserves_list}') # 希望日+希望時間帯のリストが空の場合は予約処理を中止する if bool(target_reserves_list) == False: logger.info( f'reserve process stopped. because empty reserves is not wanted.') return logger # menu_map.jsonを読み込み、Dictに保存する menu_map = reserve_tools.read_json_cfg('menu_map.json') # 複数IDに対応する userauth = cfg['userauth'] # タイプ毎のID:PASSリストを取得する for _type, _type_list in userauth.items(): # 予約できた件数が1回の最大予約件数を超えていたら終了する if whole_reserved_num >= max_whole_reserved_num: logger.info( f'exceeded whole reserved number({max_whole_reserved_num}) at onetime.' ) break # タイプ別のID:PASSリストが空の場合は次のタイプに移る if not bool(_type_list): logger.info(f'{_type} type users list is empty.') continue # 利用者ID毎に予約処理を開始する ## IDとパスワードを取得する for _userid, _credential in _type_list.items(): # ユーザー毎の予約確定件数を初期化する user_reserverd_num = 0 user_reserved_num_at_onetime = 0 # 予約できた件数が1回の最大予約件数を超えていたら終了する if whole_reserved_num >= max_whole_reserved_num: logger.info( f'exceeded whole reserved number({max_whole_reserved_num}) at onetime.' ) break _password = _credential['password'] logger.info(f'UserID:{_userid}, PASS:{_password} is logined.') # ログインIDを使ってログインする (driver, mouse) = login_proc(cfg, headers, _userid, _password, logger=logger) # 既存予約済みリストを取得するため、「予約一覧ページ」画面に移動する。予約情報リストを取得後、「空き状況を検索」画面移動する (driver, mouse, user_reserved_list) = get_current_reserves_list(driver, mouse, cfg, logger=logger) # 既存予約件数を取得する user_reserved_num = get_reserved_num(user_reserved_list, logger=logger) logger.info( f'reserved num of userID({_userid}): {user_reserved_num}') # 既存予約済みリストと希望予約リストを比較し、既存予約済みリストと日時と時間帯の予約が重なっている場合はユーザー毎の希望予約リストに追加しない (user_target_reserves_list ) = reserve_tools.create_user_target_reserves_list( target_reserves_list, user_reserved_list, logger=logger) # 予約処理を省略するためのデバッグ用 #continue # 予約処理を開始する # メニュー画面から「随時予約・抽選申込」を選択し、「空き状況を検索」画面移動する # 希望日+希望時間帯+希望コートのリストから検索条件を取得する for _date in user_target_reserves_list: # 既存予約件数が最大予約件数を超えていたら終了する if user_reserved_num >= max_user_reserved_num: logger.info( f'exceeded user reserved number({max_user_reserved_num}).' ) break # 予約できた件数が1回の予約処理の最大予約件数を超えていたら終了する if user_reserved_num_at_onetime >= max_user_reserved_num_at_onetime: logger.info( f'exceeded user reserved number({max_user_reserved_num_at_onetime}) at onetime.' ) break for _time, _court_list in user_target_reserves_list[ _date].items(): # 既存予約件数が最大予約件数を超えていたら終了する if user_reserved_num >= max_user_reserved_num: logger.info( f'exceeded user reserved number({max_user_reserved_num}).' ) break # 予約できた件数が1回の予約処理の最大予約件数を超えていたら終了する if user_reserved_num_at_onetime >= max_user_reserved_num_at_onetime: logger.info( f'exceeded user reserved number({max_user_reserved_num_at_onetime}) at onetime.' ) break for _court in _court_list: # 既存予約件数が最大予約件数を超えていたら終了する if user_reserved_num >= max_user_reserved_num: logger.info( f'exceeded user reserved number({max_user_reserved_num}).' ) break # 予約できた件数が1回の予約処理の最大予約件数を超えていたら終了する if user_reserved_num_at_onetime >= max_user_reserved_num_at_onetime: logger.info( f'exceeded reserved number({max_user_reserved_num_at_onetime}) at onetime.' ) break _facility_name = _court.split(' ')[0] _court_name = _court.split(' ')[1] _facility_id = menu_map['facility_id'][_facility_name] _court_id = menu_map['field_group_id'][_facility_name][ _court_name] logger.debug( f'input data for search: {_date} {_time} {_court} {_facility_id} {_court_id}' ) # 空き状況を検索するため、検索条件を入力して、空きコートを表示する (driver, mouse) = display_target_reserve(driver, mouse, _date, _facility_id, _court_id, logger=logger) # 表示された空きコートの空き時間帯を選択し、予約登録画面に移動する (driver, mouse) = select_empty_court_and_time(driver, mouse, cfg, _time, logger=logger) # 予約登録画面で利用目的を選択し、申込むボタンをクリックし、予約する (driver, mouse) = entry_reserve(driver, mouse, logger=logger) logger.info( f'registed reserve: {_date} {_time} {_court}') # 予約できたものは発見した空き予約リスト(昇順)から削除する # 削除しないと次の利用者IDの予約時に今予約したものを検索をしてしまうため logger.debug( f'delete from target_reserves_list: {_date} {_time} {_court}' ) _index = target_reserves_list[_date][_time].index( _court) del target_reserves_list[_date][_time][_index] # ユーザー毎と全体の予約確定件数をカウントアップする user_reserved_num_at_onetime += 1 user_reserved_num += 1 whole_reserved_num += 1 # 予約確定通知のメッセージを作成する # 八王子市は予約番号はないため、Nullとする reserved_number = 'None' # 予約確定した予約情報を作成する。共通化しているため、既存のJSONフォーマットと同じにする reserve = {_date: {_time: [_court]}} # 送信メッセージリストの初期化 message_bodies = [] message_bodies = reserve_tools.create_reserved_message( _userid, reserved_number, reserve, message_bodies, cfg, logger=logger) # LINEに送信する reserve_tools.send_line_notify(message_bodies, cfg, logger=logger) # 空き状況の検索ページへ戻る (driver, mouse) = return_to_datesearch(driver, mouse, cfg, logger=logger) # クローラーのWEBブラウザを終了する driver.quit() return logger
def main_search_empty_reserves(): """ メインルーチン """ # 祝日の初期化 public_holiday = [[], [], [], [], [], [], [], [], [], [], [], [], []] # 空き予約リストの初期化 #reserves_list = {} threadsafe_list = ThreadSafeReservesList() # 送信メッセージリストの初期化 message_bodies = [] # WEB request header headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36' } # 処理の開始 # 祝日設定ファイルを読み込んで、祝日リストを作成する reserve_tools.set_public_holiday('public_holiday.json', public_holiday) # 設定ファイルを読み込んで、設定パラメータをセットする cfg = reserve_tools.read_json_cfg('cfg.json') # ロギングを設定する logger = reserve_tools.mylogger(cfg) # スレッド数を設定する threads_num = cfg['threads_num'] # 検索リストを作成する target_months_list = reserve_tools.create_month_list(cfg, logger=logger) logger.debug(f'target months: {target_months_list}') date_list = reserve_tools.create_date_list_hachioji(target_months_list, public_holiday, cfg, logger=logger) logger.debug(f'date list: {date_list}') # スレッド数に応じて、date_listを分割する date_list_threads = split_date_list(date_list, threads_num, logger=logger) logger.debug(f'splited date list: {date_list_threads}') #return logger # マルチスレッド化する ## ここから # クローラーの初期化 #( driver, mouse ) = setup_driver(headers) # 空き予約ページにアクセスし、cookieを取得する #( cookies , response )= get_cookie(cfg) #( cookies , response )= selenium_get_cookie(driver, cfg) # 空き状況を検索するページに移動する #selenium_go_to_search_menu(driver, mouse, cfg, cookies) # 条件を指定して、空き予約を取得する #reserves_list = selenium_post_conditions(driver, date_list, reserves_list, cfg) #logger.debug(type(reserves_list)) #logger.debug(dir(reserves_list)) # seleniumを終了する #driver.quit() ## ここまで # マルチスレッドで呼び出す threadsafe_list = multi_thread_datesearch(cfg, headers, date_list_threads, threadsafe_list, threads_num=threads_num, logger=logger) logger.debug( json.dumps(threadsafe_list.reserves_list, indent=2, ensure_ascii=False)) #exit() # LINEにメッセージを送信する ## メッセージ本体を作成する reserve_tools.create_message_body(threadsafe_list.reserves_list, message_bodies, cfg, logger=logger) ## LINEに空き予約情報を送信する reserve_tools.send_line_notify(message_bodies, cfg, logger=logger) #exit() return cfg, logger, threadsafe_list.reserves_list, target_months_list, public_holiday, headers
def main(): """ メインルーチン """ # 祝日の初期化 public_holiday = [[], [], [], [], [], [], [], [], [], [], [], [], []] # 空き予約名リストの初期化 court_empty_reserves_list = {} #selected_reserve_name_list = {} reserves_list = {} # 送信メッセージの初期化 message_bodies = [] # WEBリクエストのヘッダー headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36', } # 処理の開始 # 祝日設定ファイルを読み込んで、祝日リストを作成する reserve_tools.set_public_holiday('public_holiday.json', public_holiday) # 設定ファイルを読み込んで、設定パラメータをセットする cfg = reserve_tools.read_json_cfg('cfg.json') # ロギングを設定する logger = reserve_tools.mylogger(cfg) # 検索対象月のリストを作成する target_months_list = reserve_tools.create_month_list(cfg, logger=logger) # 検索対象の開始日と終了日のリストを作成する input_data_date = create_inputdate(target_months_list, logger=logger) # 検索データを作成する input_data = create_inputdata(cfg, input_data_date, logger=logger) # フィルターリストを作成する date_string_list = reserve_tools.create_date_list(target_months_list, public_holiday, cfg) logger.debug(f'date_string_list: {date_string_list}') # 空き予約ページのトップページにアクセスし、cookieを取得する (cookies, response) = get_cookie(cfg) # 検索データを入力して、空き予約を検索する court_empty_reserves_list = do_search_empty_reserve( cfg, cookies, response, input_data, court_empty_reserves_list, logger=logger) logger.debug(f'court_empty_reserves_list: {court_empty_reserves_list}') # 空き予約名リストから希望曜日の希望時間帯のみを抽出したリストを作成する reserves_list = create_selected_reserve_list(court_empty_reserves_list, reserves_list, cfg, date_string_list, logger=logger) logger.debug(f'reserves_list: {reserves_list}') #exit() # 送信メッセージ本体を作成する message_bodies = reserve_tools.create_message_body(reserves_list, message_bodies, cfg, logger=logger) # LINE Notifyに空き予約情報のメッセージを送信する reserve_tools.send_line_notify(message_bodies, cfg, logger=logger) # 終了する #exit() return logger