You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
363 lines
16 KiB
363 lines
16 KiB
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) |