first commit

This commit is contained in:
jack
2025-11-12 15:56:25 +08:00
commit 2c0019254d
108 changed files with 51129 additions and 0 deletions
+62
View File
@@ -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})
+39
View File
@@ -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()
+90
View File
@@ -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())
+203
View File
@@ -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()
+181
View File
@@ -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())
+71
View File
@@ -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)
+197
View File
@@ -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()