import telebot from config import Config import pdfplumber import time import requests from datetime import datetime import schedule from bs4 import BeautifulSoup import requests from selenium import webdriver from selenium.webdriver.chrome.service import Service as ChromeService from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from selenium.common.exceptions import WebDriverException import pytz from selenium.webdriver.common.by import By from selenium.webdriver.chrome.options import Options from datetime import timedelta from pyvirtualdisplay import Display import threading BOT_TOKEN = '6701395239:AAFE30dqvNihDdni9vYoAbWssO-X5yAmwho' # BOT_TOKEN = "6746720034:AAEMaoV2FwIZ8pz_PF18-bo2a6gFC1eVtVs" #BOT_TOKEN = '6589162555:AAHGhrTQ0wYNtIUySMohnfpxQl1d6blr24Q' def broadcast_message(message:str,chat_id:str): r = requests.post(f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage", json={ "chat_id": chat_id, "text": message, }, ) def find_indices(lst): # 找到所有空字串的索引 empty_indices = [i for i, x in enumerate(lst) if x == ''] # 找到第二個連續兩個空字串的索引 start_index = None for i in range(1, len(empty_indices)): if empty_indices[i] - empty_indices[i-1] == 1 : if start_index is not None: # 如果已經找到第二個連續的空字串,則跳出迴圈 start_index = empty_indices[i-1] break start_index = empty_indices[i-1] # 找到下一個空字串的索引 end_index = None end_index = empty_indices[empty_indices.index(start_index)+2] return start_index+2, end_index def find_cpi(driver): try: driver.get(cpi_url) print("Open") date = driver.find_element(By.XPATH, '/html/body/div[2]/div[5]/div/div[1]/pre[1]').text.split('\n')[6].split("-")[1].split(" ")[1] value = driver.find_element(By.XPATH, '/html/body/div[2]/div[5]/div/div[1]/pre[1]').text.split('\n')[8:12] return driver, date, value except Exception as e: print(f"Error in find_cpi: {e}") return driver, None, None def find_fomc(driver, date:str): try: driver.get(fomc_url+date+".htm") print("Open") date = driver.find_element(By.CLASS_NAME, 'article__time').text.split(',')[0].split(' ')[0] value = driver.find_element(By.XPATH, '//*[@id="article"]/div[3]').text.split('.') value = [item for item in value if 'In support of' in item] return driver, date, value[0].strip('\n') except Exception as e: print(f"Error in find_fomc: {e}") return driver, None, None def find_non_farm(driver): try: driver.get(nonfarm_url) for _ in range(100): driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") # print all of the page source that was loaded print(driver.page_source.encode("utf-8")) print("Open") date = driver.title value = driver.find_element(By.XPATH, '/html/body/div[2]/div[5]/div/div[1]/pre').text.split('\n') start , end = find_indices(value) result = value[start:end] return driver, date, result except Exception as e: print(f"Error in find_non_farm: {e}") return driver, None, None def find_pce(driver, date_target:str): try: driver.get(pce_url+date_target) print("Successfully accessed the website.") time.sleep(1) date = driver.find_element(By.XPATH, '//*[@id="home"]/h1').text.split(' ')[4] value_1 = driver.find_element(By.XPATH, '//*[@id="home"]/div[2]/div/div/p[2]').text value_2 = driver.find_element(By.XPATH, '//*[@id="home"]/div[2]/div/div/div[1]/table/tbody/tr[13]').text.strip(' ').split(' ')[-1] return driver, date, value_1, value_2 except WebDriverException as e: print(e) print("Failed to access the website.") return driver, None, None, None def find_pmi(driver, date_target:str): try: driver.get(pmi_url+date_target+"/") print("Open") # time.sleep(4) agree_button = driver.find_element(By.XPATH, '//*[@id="alert-modal-disclaimer___BV_modal_body_"]/center/input') agree_button.click() date = driver.find_element(By.XPATH, '//*[@id="main"]/div[1]/div/div[2]/div/div[1]/div/div/div[1]/div[1]/h1[2]').text.split(' ')[0] value = driver.find_element(By.XPATH, '//*[@id="main"]/div[1]/div/div[2]/div/div[1]/div/div/div[1]/div[1]/p[3]').text.split('.')[0:4] #將value list 串起來成一個string value_str = ".".join(value)+"." return driver, date, value_str except Exception as e: print(f"Error in find_pmi: {e}") return driver, None, None def broadcast_all_non_farm(target:str): startimee = time.time() display = Display(visible=0, size=(1920, 1080)) display.start() driver = webdriver.Chrome(options=options) driver, date, message = find_non_farm(driver) while date != target: time.sleep(0.5) driver.refresh() print("Non Farm Refresh") driver, date, message = find_non_farm(driver) message= "\n".join(message) broadcast_message(message, "-1002033782195") endtimee = time.time() broadcast_message( f"Now :{datetime.fromtimestamp(time.time())} , Spend time :{str(round(endtimee - startimee, 3))} s", "-1002033782195") broadcast_message(f"The above is the Non Farm for {target}","-1002033782195") driver.quit() display.stop() return True def broadcast_all_cpi(target:str): startimee = time.time() display = Display(visible=0, size=(1920, 1080)) display.start() driver = webdriver.Chrome(options=options) driver, date , message = find_cpi(driver) while date != target: time.sleep(0.5) driver.refresh() print("Cpi Refresh") driver, date, message = find_cpi(driver) message= "\n".join(message) broadcast_message(message, "-1002033782195") endtimee = time.time() broadcast_message( f"Now :{datetime.fromtimestamp(time.time())} , Spend time :{str(round(endtimee - startimee, 3))} s", "-1002033782195") broadcast_message(f"The above is the CPI for {target}","-1002033782195") driver.quit() display.stop() return True def broadcast_all_fomc(target:str,date_target:str): #date_target = "20240131a" startimee = time.time() display = Display(visible=0, size=(1920, 1080)) display.start() driver = webdriver.Chrome(options=options) driver, date , message = find_fomc(driver,date_target) while date != target: time.sleep(0.5) driver.refresh() print("Fomc Refresh") driver, date, message = find_fomc(driver,date_target) broadcast_message(message, "-1002033782195") endtimee = time.time() broadcast_message( f"Now :{datetime.fromtimestamp(time.time())} , Spend time :{str(round(endtimee - startimee, 3))} s", "-1002033782195") broadcast_message(f"The above is the FOMC abstract for {target}","-1002033782195") driver.quit() display.stop() return True def broadcast_all_pce(target:str,date_target:str): startimee = time.time() display = Display(visible=0, size=(1920, 1080)) display.start() driver = webdriver.Chrome(options=options) driver, date, message1, message2 = find_pce(driver,date_target) while date != target: time.sleep(0.5) driver.refresh() print("PCE Refresh") driver, date, message1, message2 = find_pce(driver,date_target) broadcast_message(date+" PCE Data", "-1002033782195") broadcast_message(message1+'\n\n Percent change from month one year ago : '+f"**{message2}**", "-1002033782195") endtimee = time.time() broadcast_message( f"Now :{datetime.fromtimestamp(time.time())} , Spend time :{str(round(endtimee - startimee, 3))} s", "-1002033782195") broadcast_message(f"The above is the PCE for {target}","-1002033782195") driver.quit() display.stop() return True def broadcast_pmi(date_target:str): startimee = time.time() display = Display(visible=0, size=(1920, 1080)) display.start() driver = webdriver.Chrome(options=options) driver, date, value = find_pmi(driver, date_target) Up_date = date_target.capitalize() while date != Up_date: time.sleep(0.5) driver.refresh() print("PMI Refresh") driver, date, value = find_pmi(driver, date_target) broadcast_message(Up_date+" PMI Data", "-1002033782195") broadcast_message(value, "-1002033782195") endtimee = time.time() broadcast_message( f"Now :{datetime.fromtimestamp(time.time())} , Spend time :{str(round(endtimee - startimee, 3))} s", "-1002033782195") broadcast_message(f"The above is the PMI for {Up_date}","-1002033782195") driver.quit() display.stop() return True has_broadcasted = False def wrapper_function_cpi(target): global has_broadcasted time.sleep(55) result = broadcast_all_cpi(target) if result: has_broadcasted = True def wrapper_function_pce(target,date_target): global has_broadcasted time.sleep(55) result = broadcast_all_pce(target,date_target) if result: has_broadcasted = True def wrapper_function_fomc(target,date_target): global has_broadcasted time.sleep(55) result = broadcast_all_fomc(target,date_target=date_target) if result: has_broadcasted = True def wrapper_function_non_farm(target): global has_broadcasted time.sleep(55) result = broadcast_all_non_farm(target) if result: has_broadcasted = True def wrapper_function_pmi(target): global has_broadcasted time.sleep(55) result = broadcast_pmi(target) if result: has_broadcasted = True def convert_to_utc(date_str, time_str, offset_seconds=0): local_tz = pytz.timezone('Asia/Taipei') local_time = datetime.strptime(date_str + " " + time_str, "%Y/%m/%d %H:%M") local_time = local_time - timedelta(seconds=offset_seconds) # 提前 offset_seconds 秒 local_time = local_tz.localize(local_time) utc_time = local_time.astimezone(pytz.utc) return utc_time.strftime("%Y-%m-%d %H:%M") def print_hello(text): time.sleep(55) startime = time.time() startime = datetime.fromtimestamp(startime) print("Start Time:" , startime) print("Hello") print(text) return True schedules = { # convert_to_utc("2024/05/22", "17:33", 5): {"function": print_hello, "args": ["May"]}, # convert_to_utc("2024/05/22", "17:34", 5): {"function": print_hello, "args": ["June"]}, convert_to_utc("2024/06/12", "20:30", 5): {"function": wrapper_function_cpi, "args": ["MAY"]}, convert_to_utc("2024/07/11", "20:30", 5): {"function": wrapper_function_cpi, "args": ["JUNE"]}, convert_to_utc("2024/08/14", "20:30", 5): {"function": wrapper_function_cpi, "args": ["JULY"]}, convert_to_utc("2024/09/11", "20:30", 5): {"function": wrapper_function_cpi, "args": ["AUGUST"]}, convert_to_utc("2024/10/10", "20:30", 5): {"function": wrapper_function_cpi, "args": ["SEPTEMBER"]}, convert_to_utc("2024/11/13", "21:30", 5): {"function": wrapper_function_cpi, "args": ["OCTOBER"]}, convert_to_utc("2024/12/11", "21:30", 5): {"function": wrapper_function_cpi, "args": ["NOVEMBER"]}, convert_to_utc("2024/06/28", "20:30", 5): {"function": wrapper_function_pce, "args": ["May", "may-2024"]}, convert_to_utc("2024/07/26", "20:30", 5): {"function": wrapper_function_pce, "args": ["June", "june-2024"]}, convert_to_utc("2024/08/30", "20:30", 5): {"function": wrapper_function_pce, "args": ["July", "july-2024"]}, convert_to_utc("2024/09/27", "20:30", 5): {"function": wrapper_function_pce, "args": ["August", "august-2024"]}, convert_to_utc("2024/10/31", "20:30", 5): {"function": wrapper_function_pce, "args": ["September", "september-2024"]}, convert_to_utc("2024/11/27", "21:30", 5): {"function": wrapper_function_pce, "args": ["October", "october-2024"]}, convert_to_utc("2024/12/20", "21:30", 5): {"function": wrapper_function_pce, "args": ["November", "november-2024"]}, convert_to_utc("2024/06/06", "09:33", 5): {"function": wrapper_function_non_farm, "args": ["M04"]}, convert_to_utc("2024/06/07", "20:30", 5): {"function": wrapper_function_non_farm, "args": ["M05"]}, convert_to_utc("2024/07/05", "20:30", 5): {"function": wrapper_function_non_farm, "args": ["M06"]}, convert_to_utc("2024/08/02", "20:30", 5): {"function": wrapper_function_non_farm, "args": ["M07"]}, convert_to_utc("2024/09/06", "20:30", 5): {"function": wrapper_function_non_farm, "args": ["M08"]}, convert_to_utc("2024/10/04", "20:30", 5): {"function": wrapper_function_non_farm, "args": ["M09"]}, convert_to_utc("2024/11/01", "20:30", 5): {"function": wrapper_function_non_farm, "args": ["M10"]}, convert_to_utc("2024/12/06", "21:30", 5): {"function": wrapper_function_non_farm, "args": ["M11"]}, convert_to_utc("2024/06/13", "02:00", 5): {"function": wrapper_function_fomc, "args": ["June", "20240613a"]}, convert_to_utc("2024/08/01", "02:00", 5): {"function": wrapper_function_fomc, "args": ["August", "20240801a"]}, convert_to_utc("2024/09/19", "02:00", 5): {"function": wrapper_function_fomc, "args": ["September", "20240919a"]}, convert_to_utc("2024/11/08", "02:00", 5): {"function": wrapper_function_fomc, "args": ["November", "20241108a"]}, convert_to_utc("2024/12/19", "03:00", 5): {"function": wrapper_function_fomc, "args": ["December", "20241219a"]}, convert_to_utc("2024/06/05", "17:07", 5): {"function": wrapper_function_pmi, "args": ["April"]}, convert_to_utc("2024/06/12", "16:30", 5): {"function": wrapper_function_cpi, "args": ["APRIL"]}, convert_to_utc("2024/06/12", "16:33", 5): {"function": wrapper_function_fomc, "args": ["May", "20240501a"]}, } if __name__ == "__main__": global nonfarm_url, cpi_url, fomc_url, pce_url, options options = Options() # options.add_argument('--headless') options.add_argument('--no-sandbox') options.add_argument('--disable-dev-shm-usage') options.add_argument("--window-size=1920,1080") # 可以根據需要調整這個大小 options.add_argument( 'user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3') nonfarm_url = "https://www.bls.gov/news.release/empsit.nr0.htm" cpi_url = "https://www.bls.gov/news.release/cpi.nr0.htm" fomc_url = "https://www.federalreserve.gov/newsevents/pressreleases/monetary" pce_url = "https://www.bea.gov/news/2024/personal-income-and-outlays-"#january-2024 pmi_url = "https://www.ismworld.org/supply-management-news-and-reports/reports/ism-report-on-business/pmi/"#+month/ print("Start Time:" , datetime.fromtimestamp(time.time())) for times, task in schedules.items(): func = task["function"] args = task["args"] print(f"Schedule {func.__name__} at {times}") schedule.every().day.at(times.split(" ")[1]).do(threading.Thread(target=func, args=args).start) while True: schedule.run_pending() if has_broadcasted: print("Broadcast completed") has_broadcasted = False time.sleep(0.1) # Check every 0.1 seconds #NonFarm # driver = webdriver.Chrome(options=options) # driver, date, message = find_non_farm(driver) # print("Non Farm Date") # print(date) # print("Non Farm Message") # print(message) #CPI # driver , date , message = find_cpi(driver) # print(date) # print(message) #PCE #broadcast_all_pce("February", "february-2024") # date, message1, message2 = find_pce("february-2024") # print(date) # print(message1) # print(message2) #FOMC # date , message = find_fomc(fomc_url,"20240320a") # print(date) # print(message)