first commit
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
from datetime import datetime
|
||||
import json
|
||||
import httpx
|
||||
|
||||
url = "https://api.chainalert.me/"
|
||||
headers = {
|
||||
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
|
||||
}
|
||||
text = ''
|
||||
n = 0
|
||||
with httpx.Client() as client:
|
||||
for page in range(1, 5):
|
||||
payload = {
|
||||
"method": "listData",
|
||||
"params": ['', "CRYPTO_RANK_AIRDROP", page, 0, 0, '']
|
||||
}
|
||||
for retry in range(10):
|
||||
try:
|
||||
response = client.post(url, headers=headers, data=payload, timeout=3)
|
||||
except Exception as e:
|
||||
print(str(e))
|
||||
continue
|
||||
if response.status_code != 200:
|
||||
print(response.status_code)
|
||||
continue
|
||||
else:
|
||||
data = response.json()
|
||||
if not data:
|
||||
client.close()
|
||||
continue
|
||||
|
||||
try:
|
||||
data_list = data['result']
|
||||
airdrop_list = data_list[0]['data']
|
||||
airdrop_list = json.loads(airdrop_list)
|
||||
except Exception as e:
|
||||
print(str(e))
|
||||
continue
|
||||
for airdrop in airdrop_list:
|
||||
name = airdrop['name']
|
||||
rank = airdrop['rank']
|
||||
task = airdrop['item1']
|
||||
update_date = airdrop['item2']['updateDate']
|
||||
financing = airdrop['item4']
|
||||
logoUrl = airdrop['logoUrl']
|
||||
|
||||
if task == '无任务':
|
||||
continue
|
||||
if task == 'No active tasks':
|
||||
continue
|
||||
|
||||
task = '成本: {}, 耗时: {}, 任务类型: {}'.format(task.get('cost'), task.get('time'), task.get('task'))
|
||||
|
||||
text += '任务名称: {}\n排名: {}\n任务详细: {}\n更新时间: {}\n融资: {}\nlogo: {}\n'.format(name, rank, task, update_date, financing, logoUrl)
|
||||
text += '=' * 50 + '\n'
|
||||
n += 1
|
||||
break
|
||||
|
||||
if text:
|
||||
print(f'一共 {n} 条数据')
|
||||
httpx.post('https://gotify.erhe.top/message?token=Aoe0VKt-kkZnm8d', headers={'Content-Type': 'application/json'}, json={'title': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'message': text})
|
||||
@@ -0,0 +1,39 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import sys
|
||||
import os
|
||||
from playwright.sync_api import sync_playwright
|
||||
from bs4 import BeautifulSoup
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
sys.path.append(os.path.join(os.path.abspath(__file__).split('auto')[0] + 'auto'))
|
||||
from utils.utils_send_gotify import *
|
||||
|
||||
|
||||
def chaincatcher_news():
|
||||
url = "https://www.chaincatcher.com/news"
|
||||
with sync_playwright() as p:
|
||||
browser = p.chromium.launch(headless=True)
|
||||
page = browser.new_page()
|
||||
page.goto(url)
|
||||
time.sleep(2)
|
||||
start_time = time.time()
|
||||
while time.time() - start_time < 10:
|
||||
page.mouse.wheel(0, 100)
|
||||
time.sleep(0.1)
|
||||
page_content = page.content()
|
||||
browser.close()
|
||||
soup = BeautifulSoup(page_content, 'html.parser')
|
||||
contents = [span.get_text(strip=True) for span in soup.find_all('span', class_='text', attrs={'data-v-aea07cf0': True}) if "微信扫码" not in span]
|
||||
result = '\n'.join(contents)
|
||||
result += f'\n推送时间: {datetime.now().strftime("%Y年%m月%d日 %H时%M分%S秒")}'
|
||||
|
||||
if result:
|
||||
gotify_notifier = GotifyNotifier(title='ChainCatcher News', message=result, token_name='news')
|
||||
gotify_notifier.send_message()
|
||||
print(result)
|
||||
else:
|
||||
print("No news found.")
|
||||
|
||||
|
||||
chaincatcher_news()
|
||||
@@ -0,0 +1,90 @@
|
||||
import time
|
||||
import aiohttp
|
||||
import asyncio
|
||||
import json
|
||||
from fake_useragent import UserAgent
|
||||
from utils.utils_send_gotify import *
|
||||
|
||||
goto_url = 'https://app.getgrass.io/'
|
||||
|
||||
account_list = [
|
||||
'jack0210_@hotmail.com:aaaAAA111!!!',
|
||||
'yujiec0210@gmail.com:aaaAAA111!!!',
|
||||
'yujieccyj01@hotmail.com:aaaAAA111!!!',
|
||||
'yujieccyj02@hotmail.com:aaaAAA111!!!',
|
||||
'yujieccyj03@hotmail.com:aaaAAA111!!!',
|
||||
'yujieccyj04@hotmail.com:aaaAAA111!!!',
|
||||
'yujieccyj05@hotmail.com:aaaAAA111!!!',
|
||||
'yujieccyj06@hotmail.com:aaaAAA111!!!',
|
||||
'yujieccyj07@hotmail.com:aaaAAA111!!!',
|
||||
'yujieccyj08@hotmail.com:aaaAAA111!!!',
|
||||
'yujieccyj09@hotmail.com:aaaAAA111!!!',
|
||||
'yujieccyj10@hotmail.com:aaaAAA111!!!',
|
||||
'yujieccyj11@hotmail.com:aaaAAA111!!!'
|
||||
]
|
||||
|
||||
|
||||
class LoginClient:
|
||||
def __init__(self, email, password, user_agent):
|
||||
self.email = email
|
||||
self.password = password
|
||||
self.user_agent = user_agent
|
||||
self.website_headers = {
|
||||
'authority': 'api.getgrass.io',
|
||||
'accept': 'application/json, text/plain, */*',
|
||||
'accept-language': 'uk-UA,uk;q=0.9,en-US;q=0.8,en;q=0.7',
|
||||
'content-type': 'application/json',
|
||||
'origin': 'https://app.getgrass.io',
|
||||
'referer': 'https://app.getgrass.io/',
|
||||
'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
|
||||
'sec-ch-ua-mobile': '?0',
|
||||
'sec-ch-ua-platform': '"Windows"',
|
||||
'sec-fetch-dest': 'empty',
|
||||
'sec-fetch-mode': 'cors',
|
||||
'sec-fetch-site': 'same-site',
|
||||
'user-agent': self.user_agent,
|
||||
}
|
||||
|
||||
async def login(self, session):
|
||||
url = 'https://api.getgrass.io/login'
|
||||
|
||||
json_data = {
|
||||
'password': self.password,
|
||||
'username': self.email,
|
||||
}
|
||||
|
||||
try:
|
||||
response = await session.post(url, headers=self.website_headers, data=json.dumps(json_data))
|
||||
response_text = await response.text()
|
||||
if response.status != 200:
|
||||
print(f"Login failed: {response_text}")
|
||||
return None
|
||||
return await response.json()
|
||||
except aiohttp.ClientConnectionError as e:
|
||||
print(f"Connection error occurred: {e}")
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"An error occurred: {e}")
|
||||
return None
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
async def main():
|
||||
async with aiohttp.ClientSession() as session:
|
||||
for account in account_list:
|
||||
email = account.split(':')[0]
|
||||
password = account.split(':')[1]
|
||||
user_agent = UserAgent().random
|
||||
|
||||
client = LoginClient(email, password, user_agent)
|
||||
login_result = await client.login(session)
|
||||
if login_result:
|
||||
email = login_result['result']['data']['email']
|
||||
user_id = login_result['result']['data']['userId']
|
||||
print(f'account: {email}\nuser_id: {user_id}')
|
||||
|
||||
else:
|
||||
print("Login failed.")
|
||||
|
||||
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,203 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.join(os.path.abspath(__file__).split('auto')[0] + 'auto'))
|
||||
|
||||
import httpx
|
||||
from datetime import datetime
|
||||
from utils.utils_send_gotify import *
|
||||
|
||||
retry_count = 5
|
||||
|
||||
|
||||
def fetch_coin_data(target):
|
||||
url = "https://api.chainalert.me/"
|
||||
headers = {
|
||||
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
|
||||
}
|
||||
|
||||
payload = {
|
||||
"method": "listData",
|
||||
"params": [datetime.now().strftime("%Y-%m-%d"), "MARKETPRICE", '', 0, 9999.0, target]
|
||||
}
|
||||
|
||||
with httpx.Client() as client:
|
||||
try:
|
||||
response = client.post(url, headers=headers, data=payload, timeout=3)
|
||||
except Exception as e:
|
||||
# print(f"Target: {target} failed to fetch data. error: {str(e)}")
|
||||
client.close()
|
||||
return False
|
||||
if response.status_code != 200:
|
||||
client.close()
|
||||
# print(f"{target} failed to fetch data. status code: {response.status_code}")
|
||||
return False
|
||||
else:
|
||||
text = ''
|
||||
data = response.json()
|
||||
try:
|
||||
target_data = eval(data['result'][0]['data'])
|
||||
except Exception as e:
|
||||
client.close()
|
||||
raise Exception(f"Failed to parse data: {data}, error: {str(e)}")
|
||||
|
||||
target_data = target_data[0]
|
||||
|
||||
# print(target_data)
|
||||
|
||||
# 获取数据值
|
||||
name = target_data['name']
|
||||
rank = target_data['rank']
|
||||
price = target_data['item1']
|
||||
volume = target_data['item2']
|
||||
change = target_data['item3']
|
||||
market_cap = target_data['item4']
|
||||
dilute = target_data['item5']
|
||||
logoUrl = target_data['logoUrl']
|
||||
|
||||
# 拼接到 text 中
|
||||
text = '{} {} {} {} {} {}'.format(name, price, change, volume, rank, market_cap)
|
||||
print(text)
|
||||
# text += f'Name: {name}\n'
|
||||
# text += f'Ranking: {rank}\n'
|
||||
# text += f'Price: {price}\n'
|
||||
# text += f'24H Transaction Volume: {volume}\n'
|
||||
# text += f'24H Price Change: {change}\n'
|
||||
# text += f'Market Capitalization: {market_cap}\n'
|
||||
# text += f'Diluted Market Value: {dilute}\n'
|
||||
# text += f'Logo: {logoUrl}\n'
|
||||
|
||||
return text + '\n' + ('-' * len(text)) + '\n'
|
||||
|
||||
|
||||
def fetch_vix_data():
|
||||
url = "https://api.chainalert.me/"
|
||||
headers = {
|
||||
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
|
||||
}
|
||||
|
||||
payload = {
|
||||
"method": "listData",
|
||||
"params": ['', "GREEDY_INDEX", 1, 0, 1, '']
|
||||
}
|
||||
|
||||
with httpx.Client() as client:
|
||||
try:
|
||||
response = client.post(url, headers=headers, data=payload, timeout=3)
|
||||
except Exception as e:
|
||||
# print(f"failed to fetch VIX data. error: {str(e)}")
|
||||
client.close()
|
||||
return False
|
||||
if response.status_code != 200:
|
||||
client.close()
|
||||
# print(f"Failed to fetch VIX data. status code: {response.status_code}")
|
||||
return False
|
||||
else:
|
||||
data = response.json()
|
||||
vix_data = eval(data['result'][0]['data'])
|
||||
vix_data = vix_data[0]
|
||||
print(vix_data)
|
||||
greedy = vix_data['greedy']
|
||||
level = vix_data['level']
|
||||
text = f'VIX data: {greedy}\nLevel: {level}'
|
||||
return text
|
||||
|
||||
|
||||
def fetch_gas_data():
|
||||
url = "https://a5.maiziqianbao.net/api/v1/chains/EVM/1/gas_price"
|
||||
|
||||
headers = {
|
||||
"Host": "a5.maiziqianbao.net",
|
||||
"Connection": "keep-alive",
|
||||
"x-req-token": "MDbO4FsaSUPdjCdvTUs2zY4V3rnvvYatvYyjz7SfY+aCJ8r+RFm06X2dGR8eEDK7Gc5g1TLEQySEhGerRXbDT/NS+e5QAWRU68yD8m4y/aKK+TBkIv90VwvxmvYId2BVoDPDHQCGG4o3EqRWkS93eV0twYQ7w7qvNUj2e3tpDcUZYuplPyLozgYVTegFPnDk",
|
||||
"Accept": "*/*",
|
||||
"x-app-type": "iOS-5",
|
||||
"x-app-ver": "1.0.1",
|
||||
"x-app-udid": "419815AD-3015-4B5A-92CA-3BCBED24ACEC",
|
||||
"x-app-locale": "en",
|
||||
"Accept-Language": "zh-Hans-CN;q=1.0, en-CN;q=0.9",
|
||||
"Accept-Encoding": "br;q=1.0, gzip;q=0.9, deflate;q=0.8",
|
||||
"User-Agent": "MathGas/1.0.1 (MathWallet.MathGas; build:3; macOS 13.5.0) Alamofire/5.4.4"
|
||||
}
|
||||
|
||||
with httpx.Client() as client:
|
||||
response = client.get(url, headers=headers)
|
||||
if response.status_code != 200:
|
||||
client.close()
|
||||
print("Error:", response.status_code)
|
||||
return False
|
||||
|
||||
if not response.json():
|
||||
client.close()
|
||||
print("Not Find GAS Data. Error: No response")
|
||||
return False
|
||||
|
||||
remove_last_n_chars = lambda n, n_chars=9: int(str(n)[:-n_chars]) if len(str(n)) > n_chars else n
|
||||
|
||||
result = '\nGAS:\n'
|
||||
|
||||
try:
|
||||
data = response.json()['data']
|
||||
|
||||
fastest = remove_last_n_chars(data['fastest']['price'])
|
||||
fast = remove_last_n_chars(data['fast']['price'])
|
||||
standard = remove_last_n_chars(data['standard']['price'])
|
||||
low = remove_last_n_chars(data['low']['price'])
|
||||
base = remove_last_n_chars(data['base']['price'])
|
||||
print(f'fastest: {fastest} - fast: {fast} - standard: {standard} - low: {low} - base: {base}')
|
||||
result += f'fastest: {fastest}\nfast: {fast}\nstandard: {standard}\nlow: {low}\nbase: {base}'
|
||||
return result
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
text = ''
|
||||
|
||||
# 获取币币实时价格
|
||||
target_list = ['btc', 'eth', 'sol', 'grass', 'sui', 'doge', 'arb', 'ath', 'move', 'pepe', 'degen', 'act', 'plume']
|
||||
for target in target_list:
|
||||
for retry in range(1, retry_count + 1):
|
||||
result = fetch_coin_data(target)
|
||||
if result:
|
||||
text += result
|
||||
break
|
||||
else:
|
||||
print(f"{target} Failed to fetch data. retry: {retry}")
|
||||
if retry == retry_count:
|
||||
text += f"{target} Failed to fetch data. retry count: {retry}"
|
||||
|
||||
# 获取恐慌指数
|
||||
for retry in range(1, retry_count + 1):
|
||||
result = fetch_vix_data()
|
||||
if result:
|
||||
text += result + '\n\n'
|
||||
break
|
||||
else:
|
||||
print(f"Failed to fetch VIX data. retry: {retry}")
|
||||
if retry == retry_count:
|
||||
text += f"Failed to fetch VIX data. retry count: {retry}"
|
||||
|
||||
# 获取实时gas费
|
||||
for retry in range(1, retry_count + 1):
|
||||
result = fetch_gas_data()
|
||||
if result:
|
||||
text += '\n' + result + '\n\n'
|
||||
break
|
||||
else:
|
||||
# print(f"Failed to fetch Gas data. retry: {retry}")
|
||||
if retry == retry_count:
|
||||
text += f"Failed to fetch Gas data. retry count: {retry}"
|
||||
|
||||
if text:
|
||||
GotifyNotifier('Real-time coin price\n', text, 'coin').send_message()
|
||||
else:
|
||||
print('No Data')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,181 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
获取超级大乐透结果, 并匹配自己购买的号码, 配合定时执行使用
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import asyncio
|
||||
import httpx
|
||||
|
||||
sys.path.append(os.path.join(os.path.abspath(__file__).split('auto')[0] + 'auto'))
|
||||
|
||||
from utils.utils_send_gotify import GotifyNotifier
|
||||
from utils.utils_send_email import SendEmail
|
||||
|
||||
|
||||
class CheckDlt:
|
||||
def __init__(self):
|
||||
self.url = 'https://webapi.sporttery.cn/gateway/lottery/getHistoryPageListV1.qry?gameNo=85&provinceId=0&pageSize=1&isVerify=1&pageNo=1'
|
||||
self.headers = {
|
||||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
|
||||
"Accept-Encoding": "gzip, deflate, br, zstd",
|
||||
"Accept-Language": "zh-CN,zh;q=0.9",
|
||||
"Cache-Control": "max-age=0",
|
||||
"Priority": "u=0, i",
|
||||
"Sec-CH-UA": '"Not;A=Brand";v="99", "Google Chrome";v="139", "Chromium";v="139"',
|
||||
"Sec-CH-UA-Mobile": "?0",
|
||||
"Sec-CH-UA-Platform": '"macOS"',
|
||||
"Sec-Fetch-Dest": "document",
|
||||
"Sec-Fetch-Mode": "navigate",
|
||||
"Sec-Fetch-Site": "none",
|
||||
"Sec-Fetch-User": "?1",
|
||||
"Upgrade-Insecure-Requests": "1",
|
||||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36"
|
||||
}
|
||||
self.my_dlt = [
|
||||
['10', '11', '16', '17', '18', '11', '12'],
|
||||
['02', '03', '11', '12', '23', '05', '06'],
|
||||
['07', '09', '15', '17', '22', '09', '11'],
|
||||
['05', '06', '07', '34', '35', '02', '09'],
|
||||
['09', '10', '11', '21', '22', '04', '05']
|
||||
]
|
||||
|
||||
async def req(self):
|
||||
async with httpx.AsyncClient() as client:
|
||||
try:
|
||||
resp = await client.get(self.url, timeout=5)
|
||||
if resp.status_code != 200:
|
||||
print('state code: {}'.format(resp.status_code))
|
||||
log_detail = '访问失败, 状态码:{},url:{}'.format(resp.status_code, self.url)
|
||||
print(log_detail)
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f'请求失败 {e}')
|
||||
return None
|
||||
|
||||
return resp.json()
|
||||
|
||||
def data_handle(self, data):
|
||||
if not data:
|
||||
print('获取数据为空')
|
||||
return None
|
||||
|
||||
value = data.get('value')
|
||||
data_list = value.get('list')
|
||||
|
||||
if not data_list:
|
||||
print('获取数据为空')
|
||||
return None
|
||||
|
||||
result_data = []
|
||||
|
||||
for d in data_list:
|
||||
numbers = d.get('lotteryUnsortDrawresult')
|
||||
try:
|
||||
if len(numbers.split(' ')) < 7:
|
||||
continue
|
||||
except Exception as e:
|
||||
print('numbers: {}, err: {}'.format(numbers, e))
|
||||
continue
|
||||
|
||||
red_list = numbers.split(' ')[:5]
|
||||
blue_list = numbers.split(' ')[5:]
|
||||
|
||||
red_list.sort()
|
||||
blue_list.sort()
|
||||
|
||||
try:
|
||||
# 切开红球,蓝球数组
|
||||
red1 = red_list[0]
|
||||
red2 = red_list[1]
|
||||
red3 = red_list[2]
|
||||
red4 = red_list[3]
|
||||
red5 = red_list[4]
|
||||
blue1 = blue_list[0]
|
||||
blue2 = blue_list[1]
|
||||
except Exception as e:
|
||||
print('红球或蓝球数据丢失')
|
||||
continue
|
||||
|
||||
result_data.append({
|
||||
'serial': d.get('lotteryDrawNum'),
|
||||
'red1': red1 or '',
|
||||
'red2': red2 or '',
|
||||
'red3': red3 or '',
|
||||
'red4': red4 or '',
|
||||
'red5': red5 or '',
|
||||
'blue1': blue1 or '',
|
||||
'blue2': blue2 or '',
|
||||
'drawPdfUrl': d.get('drawPdfUrl'),
|
||||
'date': d.get('lotteryDrawTime'),
|
||||
'pool': d.get('poolBalanceAfterdraw')
|
||||
})
|
||||
|
||||
if result_data:
|
||||
return result_data
|
||||
else:
|
||||
print('返回的数据为空, 获取数据失败')
|
||||
return None
|
||||
|
||||
def data_compare(self, all_data):
|
||||
if not all_data:
|
||||
return '', ''
|
||||
|
||||
data = all_data[0]
|
||||
|
||||
red_list = [data['red1'], data['red2'], data['red3'], data['red4'], data['red5']]
|
||||
blue_list = [data['blue1'], data['blue2']]
|
||||
|
||||
# 期号
|
||||
subject = '{}'.format(data['serial'])
|
||||
|
||||
# 组成每期数据的text
|
||||
serial_text = 'serial: {}\t\tlottery draw date: {}\nbonus pool: {} RMB\n{}\nlottery draw num: {} + {}\n\n'.format(
|
||||
data['serial'], data['date'], data['pool'], '*' * 90,
|
||||
red_list, blue_list)
|
||||
|
||||
for my_num in self.my_dlt:
|
||||
my_red_list = my_num[:5]
|
||||
my_blue_list = my_num[5:]
|
||||
|
||||
# 使用列表推导式找出两个列表中都存在的元素
|
||||
red_common_elements = [element for element in red_list if element in my_red_list]
|
||||
blue_common_elements = [element for element in blue_list if element in my_blue_list]
|
||||
|
||||
# 计算相等元素的数量
|
||||
red_equal_count = len(red_common_elements)
|
||||
blue_equal_count = len(blue_common_elements)
|
||||
|
||||
serial_text += 'my nums: {} + {}\nred hit: {}\nblue hit: {}\n\n'.format(my_red_list, my_blue_list,
|
||||
red_equal_count,
|
||||
blue_equal_count)
|
||||
|
||||
serial_text += '{}\n\n\n\n'.format('*' * 90)
|
||||
|
||||
return serial_text, subject
|
||||
|
||||
def send_message(self, text, subject):
|
||||
if not text:
|
||||
return
|
||||
|
||||
title = f'dlt {subject}'
|
||||
|
||||
# 推送到 message
|
||||
GotifyNotifier(title, text, 'dlt').send_message()
|
||||
|
||||
# 发送到邮件
|
||||
# SendEmail(title, title, text).send()
|
||||
|
||||
async def main(self):
|
||||
data = await self.req()
|
||||
result_data = self.data_handle(data)
|
||||
if not result_data:
|
||||
return
|
||||
|
||||
text, subject = self.data_compare(result_data)
|
||||
self.send_message(text, subject)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(CheckDlt().main())
|
||||
@@ -0,0 +1,71 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
获取天气预报
|
||||
'''
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
from datetime import datetime
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
sys.path.append(os.path.join(os.path.abspath(__file__).split('auto')[0] + 'auto'))
|
||||
|
||||
from utils.utils_logs_handle import LogsHandle
|
||||
from utils.utils_send_gotify import *
|
||||
|
||||
|
||||
class Weather():
|
||||
def __init__(self):
|
||||
self.email_subject = '天气预报'
|
||||
self.email_title = 'Weather forecast'
|
||||
self.email_text = '获取数据时间:\n{0}\n{1}\n\n\n\n'.format(datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
('-' * 90))
|
||||
self.logs_handle = LogsHandle()
|
||||
self.now_day = time.strftime('%Y-%m-%d', time.localtime())
|
||||
|
||||
def main(self):
|
||||
self.logs_handle.logs_write('Weather forecast', '开始获取天气预报数据', 'start', False)
|
||||
try:
|
||||
area_code = '59287'
|
||||
one_week = [
|
||||
'/tomorrow-%s.htm' % area_code,
|
||||
'/third-%s.htm' % area_code,
|
||||
'/fourth-%s.htm' % area_code,
|
||||
'/fifth-%s.htm' % area_code,
|
||||
'/sixth-%s.htm' % area_code,
|
||||
'/seventh-%s.htm' % area_code,
|
||||
]
|
||||
url = "https://tianqi.2345.com/today-%s.htm" % area_code
|
||||
header = {
|
||||
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; Media Center PC 6.0; InfoPath.2; MS-RTC LM 8'
|
||||
}
|
||||
response = httpx.get(url=url, headers=header) # 增加headers参数,简单伪装UA
|
||||
response.encoding = "utf-8"
|
||||
bs = BeautifulSoup(response.text, 'html.parser') # 这里我们用html.parser解析器
|
||||
|
||||
one_week_weather = []
|
||||
for week in one_week:
|
||||
a = bs.find_all('a', href=week) # 查找对应元素
|
||||
a = ' '.join(a[0].text.split())
|
||||
one_week_weather.append(a)
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
self.logs_handle.logs_write('Weather forecast', e, 'error', False)
|
||||
exit(0)
|
||||
|
||||
text = "天气预报: {}获取并发送\n".format(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())) + '\n'.join(
|
||||
one_week_weather)
|
||||
|
||||
# 推送到 message
|
||||
GotifyNotifier('天气预报数', text, 'weather').send_message()
|
||||
|
||||
self.logs_handle.logs_write('Weather forecast', '天气预报数据已获取', 'done', False)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
L = LogsHandle()
|
||||
L.logs_write('Weather forecast', '开始获取天气预报数据', 'start', False)
|
||||
W = Weather()
|
||||
W.main()
|
||||
L.logs_write('Weather forecast', '天气预报数据已获取', 'done', False)
|
||||
@@ -0,0 +1,197 @@
|
||||
import smtplib
|
||||
from email.mime.text import MIMEText
|
||||
from email.header import Header
|
||||
import datetime
|
||||
import re
|
||||
import psycopg2
|
||||
from psycopg2 import Error
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
|
||||
|
||||
class FreshRSSDatabase:
|
||||
def __init__(self):
|
||||
self.hostname = 'erhe.top'
|
||||
self.port = 20788
|
||||
self.database = 'freshrss'
|
||||
self.user = 'freshrss'
|
||||
self.password = 'freshrss'
|
||||
self.conn = None
|
||||
self.keys = [
|
||||
{'web3新闻': 'web3|区块链|NFT|DeFi|NFT'},
|
||||
{'购物类新闻': '大疆|无人机|硬盘|鼠标|纸巾|穿越机|礼物'},
|
||||
{'coin新闻': 'btc|eth|sui|degen'}
|
||||
]
|
||||
self.ellipsis = 300
|
||||
self.days = 3
|
||||
|
||||
def connect(self):
|
||||
"""连接到 PostgreSQL 数据库"""
|
||||
try:
|
||||
self.conn = psycopg2.connect(
|
||||
dbname=self.database,
|
||||
user=self.user,
|
||||
password=self.password,
|
||||
host=self.hostname,
|
||||
port=self.port
|
||||
)
|
||||
except Error as e:
|
||||
print(f"Error connecting to the database: {e}")
|
||||
raise # 重新抛出异常
|
||||
|
||||
def execute_query(self, keywords):
|
||||
"""执行 SQL 查询并返回结果"""
|
||||
if self.conn is None:
|
||||
self.connect()
|
||||
if self.conn is None:
|
||||
print("Database connection failed")
|
||||
return None
|
||||
try:
|
||||
cur = self.conn.cursor()
|
||||
conditions = [f"title ILIKE '%{keyword}%' AND content ILIKE '%{keyword}%'" for keyword in
|
||||
keywords.split('|')]
|
||||
sql = f"""
|
||||
SELECT *
|
||||
FROM freshrss_toor_entry
|
||||
WHERE {" OR ".join(conditions)}
|
||||
AND date > EXTRACT(EPOCH FROM NOW() - INTERVAL '1 day')
|
||||
ORDER BY date DESC;
|
||||
"""
|
||||
|
||||
cur.execute(sql)
|
||||
records = cur.fetchall()
|
||||
cur.close()
|
||||
return records
|
||||
except Error as e:
|
||||
print(f"An error occurred: {e}")
|
||||
return None
|
||||
|
||||
def close(self):
|
||||
"""关闭数据库连接"""
|
||||
if self.conn:
|
||||
self.conn.close()
|
||||
|
||||
def remove_all_html_tags(self, text):
|
||||
"""
|
||||
移除字符串中的所有 HTML 标签。
|
||||
|
||||
参数:
|
||||
text (str): 包含 HTML 标签的原始文本。
|
||||
|
||||
返回:
|
||||
str: 移除所有 HTML 标签后的文本。
|
||||
"""
|
||||
clean_text = re.sub(r'<[^>]+>', '', text)
|
||||
clean_text = clean_text.replace(' ', '')
|
||||
clean_text = clean_text.replace('\n', '')
|
||||
if len(clean_text) > self.ellipsis:
|
||||
clean_text = clean_text[:self.ellipsis] + '...'
|
||||
return clean_text
|
||||
|
||||
def send_email(self, subject='', title='', text=''):
|
||||
mail_host = "smtp.163.com"
|
||||
mail_user = "pushmessagebot@163.com"
|
||||
mail_pass = "WSMSRKBKXIHIQWTU"
|
||||
|
||||
sender = "pushmessagebot@163.com"
|
||||
receivers = ["pushmessagebot@163.com"]
|
||||
|
||||
message = MIMEText(text, 'plain', 'utf-8')
|
||||
message['From'] = Header(title, 'utf-8')
|
||||
message['To'] = Header("RSS data", 'utf-8')
|
||||
message['Subject'] = Header(subject, 'utf-8')
|
||||
|
||||
try:
|
||||
smtpObj = smtplib.SMTP_SSL(mail_host)
|
||||
smtpObj.login(mail_user, mail_pass)
|
||||
smtpObj.sendmail(sender, receivers, message.as_string())
|
||||
print(f"{title} 邮件发送成功")
|
||||
except smtplib.SMTPException as e:
|
||||
print("Error: 无法发送邮件", e)
|
||||
|
||||
def query_and_process_key(self, key_name, keywords):
|
||||
records = self.execute_query(keywords)
|
||||
if records:
|
||||
unique_records = {}
|
||||
for record in records:
|
||||
title = self.remove_all_html_tags(record[2]) # 获取标题
|
||||
if title not in unique_records:
|
||||
unique_records[title] = {
|
||||
"title": title,
|
||||
"content": self.remove_all_html_tags(record[4]),
|
||||
"link": record[5],
|
||||
"postdate": (datetime.datetime.utcfromtimestamp(record[7])
|
||||
.strftime('%Y-%m-%d %H:%M:%S')) if record[7] else '',
|
||||
"posttimestamp": record[7] or 0
|
||||
}
|
||||
return list(unique_records.values())
|
||||
return None
|
||||
|
||||
def prepare_to_send(self, data):
|
||||
source_key = data.get('source_key')
|
||||
keys = data.get('keys')
|
||||
data_list = data.get('data')
|
||||
|
||||
filter_data = []
|
||||
|
||||
# 计算过去一天的时间戳
|
||||
one_day_ago = datetime.datetime.now() - datetime.timedelta(days=self.days)
|
||||
# 将 datetime 对象转换为时间戳
|
||||
one_day_ago_timestamp = one_day_ago.timestamp()
|
||||
|
||||
for value in data_list:
|
||||
if value['posttimestamp'] >= one_day_ago_timestamp:
|
||||
filter_data.append(value)
|
||||
|
||||
sorted_list = sorted(filter_data, key=lambda x: x['posttimestamp'], reverse=True)
|
||||
|
||||
subject = 'RSS' + data.get('source_key')
|
||||
title = source_key
|
||||
|
||||
key_data_total = len(data.get('data'))
|
||||
text = '关键词:\n' + data.get('keys').replace('|', '\n') + '\n\n'
|
||||
text += '一共搜索到: ' + str(key_data_total) + ' 条数据\n\n'
|
||||
text += '*' * 80 + '\n'
|
||||
for d in sorted_list:
|
||||
text += '标题: ' + d.get('title') + '\n'
|
||||
text += '内容: ' + d.get('content') + '\n'
|
||||
text += '链接: ' + d.get('link') + '\n'
|
||||
text += '发布日期: ' + d.get('postdate') + '\n'
|
||||
text += '时间戳: ' + str(d.get('posttimestamp')) + '\n\n'
|
||||
text += '*' * 80
|
||||
text += '\n\n'
|
||||
|
||||
self.send_email(subject=subject, title=title, text=text)
|
||||
|
||||
def main(self):
|
||||
# 执行查询
|
||||
loaded_data = {}
|
||||
with ThreadPoolExecutor(max_workers=len(self.keys)) as executor:
|
||||
future_to_key = {executor.submit(self.query_and_process_key, k, v): (k, v) for sublist in self.keys for k, v
|
||||
in sublist.items()}
|
||||
for future in as_completed(future_to_key):
|
||||
key_name, keywords = future_to_key[future]
|
||||
try:
|
||||
data = future.result()
|
||||
if data:
|
||||
loaded_data[key_name] = {
|
||||
'source_key': key_name,
|
||||
'keys': keywords,
|
||||
'data': data
|
||||
}
|
||||
else:
|
||||
print(f'key: {key_name} 数据为空')
|
||||
except Exception as exc:
|
||||
print(f'{key_name} generated an exception: {exc}')
|
||||
|
||||
# 关闭数据库连接
|
||||
self.close()
|
||||
|
||||
for source_key, data in loaded_data.items():
|
||||
self.prepare_to_send(data)
|
||||
|
||||
print('done!')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
f = FreshRSSDatabase()
|
||||
f.main()
|
||||
Reference in New Issue
Block a user