commit
756cb1e7d8
@ -0,0 +1,65 @@ |
|||||||
|
.DS_Store |
||||||
|
# Byte-compiled / optimized / DLL files |
||||||
|
__pycache__/ |
||||||
|
*.py[cod] |
||||||
|
*$py.class |
||||||
|
|
||||||
|
# C extensions |
||||||
|
*.so |
||||||
|
|
||||||
|
# Distribution / packaging |
||||||
|
.Python |
||||||
|
env/ |
||||||
|
build/ |
||||||
|
develop-eggs/ |
||||||
|
dist/ |
||||||
|
downloads/ |
||||||
|
eggs/ |
||||||
|
.eggs/ |
||||||
|
lib/ |
||||||
|
lib64/ |
||||||
|
parts/ |
||||||
|
sdist/ |
||||||
|
var/ |
||||||
|
*.egg-info/ |
||||||
|
.installed.cfg |
||||||
|
*.egg |
||||||
|
.idea/* |
||||||
|
xml_files/ |
||||||
|
|
||||||
|
# PyInstaller |
||||||
|
# Usually these files are written by a python script from a template |
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it. |
||||||
|
*.manifest |
||||||
|
*.spec |
||||||
|
|
||||||
|
# Installer logs |
||||||
|
pip-log.txt |
||||||
|
pip-delete-this-directory.txt |
||||||
|
|
||||||
|
# Unit test / coverage reports |
||||||
|
htmlcov/ |
||||||
|
.tox/ |
||||||
|
.coverage |
||||||
|
.coverage.* |
||||||
|
.cache |
||||||
|
nosetests.xml |
||||||
|
coverage.xml |
||||||
|
*,cover |
||||||
|
|
||||||
|
# Translations |
||||||
|
*.mo |
||||||
|
*.pot |
||||||
|
|
||||||
|
# Django stuff: |
||||||
|
*.log |
||||||
|
|
||||||
|
# Sphinx documentation |
||||||
|
docs/_build/ |
||||||
|
|
||||||
|
# PyBuilder |
||||||
|
target/ |
||||||
|
|
||||||
|
other/split_clash_config/split_config |
||||||
|
ai_news/save_data |
||||||
|
daily/*.txt |
||||||
@ -0,0 +1,80 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
# 检查所有节点是否有重复 |
||||||
|
import asyncio |
||||||
|
import httpx |
||||||
|
from typing import Optional, Dict, Any, List, Tuple |
||||||
|
|
||||||
|
async def check_now_node(url_and_port: str) -> Optional[str]: |
||||||
|
"""检测当前节点并设置全局代理""" |
||||||
|
|
||||||
|
async with httpx.AsyncClient(timeout=10.0) as client: |
||||||
|
try: |
||||||
|
# 设置全局模式 |
||||||
|
set_url = f"http://{url_and_port}/api/configs" |
||||||
|
set_data = {"mode": "Global"} |
||||||
|
set_response = await client.patch(set_url, json=set_data) |
||||||
|
set_response.raise_for_status() |
||||||
|
|
||||||
|
# 获取代理信息 |
||||||
|
get_url = f"http://{url_and_port}/api/proxies" |
||||||
|
get_response = await client.get(get_url) |
||||||
|
get_response.raise_for_status() |
||||||
|
|
||||||
|
json_data = get_response.json() |
||||||
|
proxies: Dict[str, Any] = json_data.get("proxies", {}) |
||||||
|
proxy_global: Dict[str, Any] = proxies.get("GLOBAL", {}) |
||||||
|
now_proxy: Optional[str] = proxy_global.get("now") |
||||||
|
|
||||||
|
return now_proxy |
||||||
|
|
||||||
|
except httpx.HTTPError as exc: |
||||||
|
print(f"请求失败 {url_and_port}: {exc}") |
||||||
|
return None |
||||||
|
|
||||||
|
async def batch_check_nodes(ip: str, ports: List[str]) -> Dict[str, Optional[str]]: |
||||||
|
"""批量检测节点""" |
||||||
|
tasks = [check_now_node(f"{ip}:{port}") for port in ports] |
||||||
|
results = await asyncio.gather(*tasks) |
||||||
|
|
||||||
|
return { |
||||||
|
f"{ip}:{port}": result |
||||||
|
for port, result in zip(ports, results) |
||||||
|
} |
||||||
|
|
||||||
|
def find_duplicate_nodes(results: Dict[str, Optional[str]]) -> List[Tuple[str, str]]: |
||||||
|
"""查找重复的节点""" |
||||||
|
node_to_urls = {} |
||||||
|
for url, node in results.items(): |
||||||
|
if node: # 只处理成功检测的节点 |
||||||
|
if node not in node_to_urls: |
||||||
|
node_to_urls[node] = [] |
||||||
|
node_to_urls[node].append(url) |
||||||
|
|
||||||
|
# 找出有重复的节点 |
||||||
|
duplicates = [] |
||||||
|
for node, urls in node_to_urls.items(): |
||||||
|
if len(urls) > 1: |
||||||
|
for i in range(len(urls)): |
||||||
|
for j in range(i + 1, len(urls)): |
||||||
|
duplicates.append((urls[i], urls[j])) |
||||||
|
|
||||||
|
return duplicates |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
ip = '192.168.31.201' |
||||||
|
ports = [f'{58000 + i}' for i in range(1, 11)] |
||||||
|
|
||||||
|
results = asyncio.run(batch_check_nodes(ip, ports)) |
||||||
|
|
||||||
|
# 输出所有节点信息 |
||||||
|
for url, node in results.items(): |
||||||
|
print(f"{url}: {node or '检测失败'}") |
||||||
|
|
||||||
|
# 检查并输出重复节点 |
||||||
|
duplicates = find_duplicate_nodes(results) |
||||||
|
if duplicates: |
||||||
|
print("\n发现重复节点:") |
||||||
|
for url1, url2 in duplicates: |
||||||
|
print(f"{url1} 和 {url2} 重复") |
||||||
|
else: |
||||||
|
print("\n没有发现重复节点") |
||||||
@ -0,0 +1,39 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
# 所有节点切换为全局 |
||||||
|
import asyncio |
||||||
|
import httpx |
||||||
|
|
||||||
|
async def set_global(url_and_port): |
||||||
|
url = f"http://{url_and_port}" |
||||||
|
key = "/api/configs" |
||||||
|
full_url = url + key |
||||||
|
|
||||||
|
data = {"mode": "Global"} |
||||||
|
headers = {"Content-Type": "application/json"} |
||||||
|
|
||||||
|
async with httpx.AsyncClient(timeout=10.0) as client: |
||||||
|
try: |
||||||
|
response = await client.patch(full_url, json=data, headers=headers) |
||||||
|
response.raise_for_status() # 自动抛出4xx/5xx异常 |
||||||
|
print(f"成功设置 {url_and_port}") |
||||||
|
return True |
||||||
|
except httpx.HTTPError as exc: |
||||||
|
print(f"请求失败 {url_and_port}: {exc}") |
||||||
|
return False |
||||||
|
|
||||||
|
async def main(): |
||||||
|
ip = '192.168.31.201' |
||||||
|
port_list = [f'{58000 + i}' for i in range(1, 11)] # 生成端口列表 |
||||||
|
|
||||||
|
# 创建任务列表 |
||||||
|
tasks = [set_global(f"{ip}:{port}") for port in port_list] |
||||||
|
|
||||||
|
# 并发执行所有任务 |
||||||
|
results = await asyncio.gather(*tasks) |
||||||
|
|
||||||
|
# 统计结果 |
||||||
|
success_count = sum(results) |
||||||
|
print(f"\n完成设置: {success_count}/{len(port_list)} 个代理成功") |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
asyncio.run(main()) |
||||||
@ -0,0 +1,180 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
""" |
||||||
|
获取超级大乐透结果, 并匹配自己购买的号码, 配合定时执行使用 |
||||||
|
""" |
||||||
|
|
||||||
|
import sys |
||||||
|
import os |
||||||
|
import asyncio |
||||||
|
import httpx |
||||||
|
|
||||||
|
sys.path.append(os.path.join(os.path.abspath(__file__).split('manual')[0] + 'manual')) |
||||||
|
|
||||||
|
from utils.utils_send_gotify import GotifyNotifier |
||||||
|
|
||||||
|
|
||||||
|
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,171 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
""" |
||||||
|
获取超级大乐透结果, 并匹配自己购买的号码, 配合定时执行使用 |
||||||
|
""" |
||||||
|
|
||||||
|
import sys |
||||||
|
import os |
||||||
|
import asyncio |
||||||
|
import httpx |
||||||
|
|
||||||
|
sys.path.append(os.path.join(os.path.abspath(__file__).split('manual')[0] + 'manual')) |
||||||
|
|
||||||
|
from utils.utils_send_gotify import GotifyNotifier |
||||||
|
|
||||||
|
|
||||||
|
class CheckDlt: |
||||||
|
def __init__(self): |
||||||
|
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, url): |
||||||
|
async with httpx.AsyncClient() as client: |
||||||
|
try: |
||||||
|
resp = await client.get(url, timeout=5) |
||||||
|
if resp.status_code != 200: |
||||||
|
print('state code: {}'.format(resp.status_code)) |
||||||
|
log_detail = '访问失败, 状态码:{},url:{}'.format(resp.status_code, 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') |
||||||
|
if not value: |
||||||
|
print('获取数据为空') |
||||||
|
return None |
||||||
|
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 |
||||||
|
|
||||||
|
async def main(self): |
||||||
|
for no in range(3, 0, -1): |
||||||
|
url = f'https://webapi.sporttery.cn/gateway/lottery/getHistoryPageListV1.qry?gameNo=85&provinceId=0&pageSize=1&isVerify=1&pageNo={no}' |
||||||
|
data_list = await self.req(url) |
||||||
|
result_data = self.data_handle(data_list) |
||||||
|
if not result_data: |
||||||
|
continue |
||||||
|
|
||||||
|
text, subject = self.data_compare(result_data) |
||||||
|
print(text) |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
asyncio.run(CheckDlt().main()) |
||||||
@ -0,0 +1,247 @@ |
|||||||
|
aiodns==3.2.0 |
||||||
|
aiofiles==24.1.0 |
||||||
|
aiogram==3.18.0 |
||||||
|
aiohappyeyeballs==2.4.6 |
||||||
|
aiohttp==3.9.5 |
||||||
|
aiohttp-socks==0.8.4 |
||||||
|
aioquic==1.2.0 |
||||||
|
aiosignal==1.3.2 |
||||||
|
annotated-types==0.7.0 |
||||||
|
anyio==4.1.0 |
||||||
|
appdirs==1.4.4 |
||||||
|
APScheduler==3.10.4 |
||||||
|
asgiref==3.8.1 |
||||||
|
async-timeout==4.0.3 |
||||||
|
atomicwrites==1.4.1 |
||||||
|
attrs==25.1.0 |
||||||
|
base58==2.1.1 |
||||||
|
beautifulsoup4==4.12.2 |
||||||
|
bech32==1.2.0 |
||||||
|
better-proxy==1.1.5 |
||||||
|
bidict==0.23.1 |
||||||
|
bitarray==3.1.0 |
||||||
|
blessed==1.20.0 |
||||||
|
blinker==1.9.0 |
||||||
|
Brotli==1.1.0 |
||||||
|
bs4==0.0.1 |
||||||
|
cairocffi==1.7.1 |
||||||
|
CairoSVG==2.7.1 |
||||||
|
captchatools==1.5.0 |
||||||
|
ccxt==4.4.75 |
||||||
|
certifi==2025.1.31 |
||||||
|
cffi==1.16.0 |
||||||
|
charset-normalizer==3.4.1 |
||||||
|
ckzg==2.0.1 |
||||||
|
click==8.1.7 |
||||||
|
colorama==0.4.6 |
||||||
|
coloredlogs==15.0.1 |
||||||
|
cryptography==36.0.1 |
||||||
|
cssselect2==0.8.0 |
||||||
|
curl_cffi==0.10.0 |
||||||
|
customtkinter==5.2.2 |
||||||
|
Cython==3.1.2 |
||||||
|
cytoolz==1.0.1 |
||||||
|
darkdetect==0.8.0 |
||||||
|
dateparser==1.1.3 |
||||||
|
ddddocr==1.5.6 |
||||||
|
defusedxml==0.7.1 |
||||||
|
distro==1.9.0 |
||||||
|
dnspython==2.4.2 |
||||||
|
docutils==0.21.2 |
||||||
|
dukpy==0.4.0 |
||||||
|
easy-clash-tool==0.0.3 |
||||||
|
easy-spider-tool==1.0.16 |
||||||
|
editor==1.6.6 |
||||||
|
et_xmlfile==2.0.0 |
||||||
|
eth-account==0.13.5 |
||||||
|
eth-hash==0.7.1 |
||||||
|
eth-keyfile==0.8.1 |
||||||
|
eth-keys==0.6.1 |
||||||
|
eth-rlp==2.2.0 |
||||||
|
eth-typing==5.2.0 |
||||||
|
eth-utils==5.2.0 |
||||||
|
eth_abi==5.2.0 |
||||||
|
exceptiongroup==1.2.0 |
||||||
|
fake-useragent==1.5.1 |
||||||
|
Faker==23.2.1 |
||||||
|
fastapi==0.115.12 |
||||||
|
Flask==3.1.0 |
||||||
|
flatbuffers==25.2.10 |
||||||
|
frozenlist==1.5.0 |
||||||
|
greenlet==3.1.1 |
||||||
|
h11==0.14.0 |
||||||
|
h2==4.1.0 |
||||||
|
hexbytes==1.3.0 |
||||||
|
hpack==4.0.0 |
||||||
|
httpcore==1.0.2 |
||||||
|
httptools==0.6.4 |
||||||
|
httpx==0.27.2 |
||||||
|
humanfriendly==10.0 |
||||||
|
hyperframe==6.0.1 |
||||||
|
idna==3.10 |
||||||
|
ifaddr==0.2.0 |
||||||
|
importlib-metadata==7.0.0 |
||||||
|
inquirer==3.4.0 |
||||||
|
itsdangerous==2.2.0 |
||||||
|
jieba==0.42.1 |
||||||
|
Jinja2==3.1.6 |
||||||
|
jiter==0.5.0 |
||||||
|
jsonpath==0.82 |
||||||
|
jsonschema==4.23.0 |
||||||
|
jsonschema-specifications==2023.12.1 |
||||||
|
kaitaistruct==0.10 |
||||||
|
ldap3==2.9.1 |
||||||
|
loguru==0.7.3 |
||||||
|
lxml==5.3.0 |
||||||
|
magic-filter==1.0.12 |
||||||
|
markdown-it-py==3.0.0 |
||||||
|
markdown2==2.5.3 |
||||||
|
MarkupSafe==3.0.2 |
||||||
|
matrix-client==0.4.0 |
||||||
|
matrix-nio==0.25.0 |
||||||
|
mdurl==0.1.2 |
||||||
|
mitmproxy==11.0.2 |
||||||
|
mitmproxy-macos==0.10.7 |
||||||
|
mitmproxy_rs==0.10.7 |
||||||
|
mnemonic==0.21 |
||||||
|
MouseInfo==0.1.3 |
||||||
|
mpmath==1.3.0 |
||||||
|
msgpack==1.1.0 |
||||||
|
multidict==6.1.0 |
||||||
|
mutf8==1.0.6 |
||||||
|
names==0.3.0 |
||||||
|
nicegui==2.14.1 |
||||||
|
numpy==1.26.4 |
||||||
|
ollama==0.4.6 |
||||||
|
onnxruntime==1.16.3 |
||||||
|
openai==1.42.0 |
||||||
|
opencv-python-headless==4.11.0.86 |
||||||
|
openpyxl==3.1.5 |
||||||
|
orjson==3.10.16 |
||||||
|
outcome==1.3.0.post0 |
||||||
|
packaging==23.2 |
||||||
|
paho-mqtt==2.1.0 |
||||||
|
pandas==2.2.3 |
||||||
|
parsimonious==0.10.0 |
||||||
|
passlib==1.7.4 |
||||||
|
patchright==1.50.0 |
||||||
|
pillow==11.1.0 |
||||||
|
ping3==4.0.4 |
||||||
|
playwright==1.46.0 |
||||||
|
primp==0.14.0 |
||||||
|
prompt_toolkit==3.0.50 |
||||||
|
propcache==0.3.0 |
||||||
|
protobuf==5.29.3 |
||||||
|
pscript==0.7.7 |
||||||
|
psycopg2==2.9.9 |
||||||
|
publicsuffix2==2.20191221 |
||||||
|
py-solc-x==2.0.3 |
||||||
|
pyasn1==0.5.1 |
||||||
|
pyasn1_modules==0.4.1 |
||||||
|
PyAutoGUI==0.9.54 |
||||||
|
pycares==4.6.0 |
||||||
|
pycparser==2.21 |
||||||
|
pycryptodome==3.21.0 |
||||||
|
pydantic==2.10.6 |
||||||
|
pydantic_core==2.27.2 |
||||||
|
pydivert==2.1.0 |
||||||
|
pyee==12.1.1 |
||||||
|
PyExecJS==1.5.1 |
||||||
|
PyGetWindow==0.0.9 |
||||||
|
Pygments==2.19.1 |
||||||
|
pygpt4all==1.1.0 |
||||||
|
pygptj==2.0.3 |
||||||
|
pyhttpx==2.10.9 |
||||||
|
pyllamacpp==2.4.2 |
||||||
|
pylsqpack==0.3.19 |
||||||
|
pymongo==4.6.1 |
||||||
|
PyMsgBox==1.0.9 |
||||||
|
PyNaCl==1.5.0 |
||||||
|
pynocaptcha==2.0.52 |
||||||
|
pyobjc-core==11.0 |
||||||
|
pyobjc-framework-Cocoa==11.0 |
||||||
|
pyobjc-framework-Quartz==11.0 |
||||||
|
pyOpenSSL==21.0.0 |
||||||
|
pyparsing==3.1.1 |
||||||
|
pyperclip==1.9.0 |
||||||
|
pyppeteer==2.0.0 |
||||||
|
PyRect==0.2.0 |
||||||
|
PyRSS2Gen==1.1 |
||||||
|
PyScreeze==1.0.1 |
||||||
|
pyshark==0.6 |
||||||
|
PySocks==1.7.1 |
||||||
|
python-dateutil==2.9.0.post0 |
||||||
|
python-dotenv==1.1.0 |
||||||
|
python-engineio==4.12.0 |
||||||
|
python-multipart==0.0.20 |
||||||
|
python-socketio==5.13.0 |
||||||
|
python-socks==2.5.1 |
||||||
|
pytweening==1.2.0 |
||||||
|
pytz==2025.1 |
||||||
|
pyunormalize==16.0.0 |
||||||
|
PyYAML==6.0.2 |
||||||
|
questionary==2.1.0 |
||||||
|
RandomWords==0.4.0 |
||||||
|
readchar==4.2.1 |
||||||
|
redis==5.0.1 |
||||||
|
referencing==0.35.1 |
||||||
|
regex==2024.11.6 |
||||||
|
requests==2.32.3 |
||||||
|
retrying==1.3.4 |
||||||
|
rich==13.9.4 |
||||||
|
rlp==4.1.0 |
||||||
|
rpds-py==0.20.0 |
||||||
|
rsa==4.8 |
||||||
|
ruamel.yaml==0.18.6 |
||||||
|
ruamel.yaml.clib==0.2.12 |
||||||
|
rubicon-objc==0.5.0 |
||||||
|
runs==1.2.2 |
||||||
|
scapy==2.5.0 |
||||||
|
schedule==1.2.1 |
||||||
|
screeninfo==0.8.1 |
||||||
|
selenium==4.16.0 |
||||||
|
selenium-wire==5.1.0 |
||||||
|
service-identity==24.2.0 |
||||||
|
simple-websocket==1.1.0 |
||||||
|
six==1.16.0 |
||||||
|
sniffio==1.3.0 |
||||||
|
sortedcontainers==2.4.0 |
||||||
|
soupsieve==2.5 |
||||||
|
SQLAlchemy==2.0.36 |
||||||
|
starlette==0.46.2 |
||||||
|
sui-brownie==1.2.4 |
||||||
|
sympy==1.13.3 |
||||||
|
tabulate==0.9.0 |
||||||
|
tenacity==8.2.3 |
||||||
|
termcolor==2.4.0 |
||||||
|
tinycss2==1.4.0 |
||||||
|
toml==0.10.2 |
||||||
|
toolz==1.0.0 |
||||||
|
tornado==6.4.2 |
||||||
|
tqdm==4.66.1 |
||||||
|
trio==0.23.1 |
||||||
|
trio-websocket==0.11.1 |
||||||
|
types-requests==2.32.0.20250301 |
||||||
|
typing_extensions==4.12.2 |
||||||
|
tzdata==2025.2 |
||||||
|
tzlocal==5.2 |
||||||
|
unpaddedbase64==2.1.0 |
||||||
|
urllib3==2.3.0 |
||||||
|
urwid==2.6.16 |
||||||
|
uvicorn==0.29.0 |
||||||
|
uvloop==0.21.0 |
||||||
|
vbuild==0.8.2 |
||||||
|
watchfiles==1.0.5 |
||||||
|
wcwidth==0.2.13 |
||||||
|
web3==7.8.0 |
||||||
|
webencodings==0.5.1 |
||||||
|
websockets==13.1 |
||||||
|
Werkzeug==3.1.3 |
||||||
|
win32_setctime==1.2.0 |
||||||
|
wsproto==1.2.0 |
||||||
|
xmltodict==0.13.0 |
||||||
|
xmod==1.8.1 |
||||||
|
yarl==1.18.3 |
||||||
|
you-get==0.4.1730 |
||||||
|
zipp==3.17.0 |
||||||
|
zstandard==0.22.0 |
||||||
@ -0,0 +1,33 @@ |
|||||||
|
import httpx |
||||||
|
|
||||||
|
content = "简单讲解一下mvc模型上下文" |
||||||
|
key = "sk-mepewzmlykchrjosberepdvvbnrjbhoamewefnckokitveqf" |
||||||
|
model = "THUDM/GLM-4.1V-9B-Thinking" |
||||||
|
url = "https://api.siliconflow.cn/v1/chat/completions" |
||||||
|
|
||||||
|
headers = { |
||||||
|
"Authorization": f"Bearer {key}", |
||||||
|
"Content-Type": "application/json" |
||||||
|
} |
||||||
|
payload = { |
||||||
|
"model": model, |
||||||
|
"messages": [{"role": "user", "content": content}] |
||||||
|
} |
||||||
|
|
||||||
|
with httpx.Client(timeout=999) as client: |
||||||
|
response = client.post(url, headers=headers, json=payload) |
||||||
|
if response.json()["choices"][0]["message"]["content"]: |
||||||
|
content = response.json()["choices"][0]["message"]["content"] |
||||||
|
content = content.split("\n") |
||||||
|
for i in content: |
||||||
|
print(i) |
||||||
|
else: |
||||||
|
print(response.json()) |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,98 @@ |
|||||||
|
import time |
||||||
|
|
||||||
|
import psycopg2 |
||||||
|
from psycopg2 import Error |
||||||
|
|
||||||
|
|
||||||
|
class CreateRssRecord(object): |
||||||
|
def __init__(self): |
||||||
|
self.hostname = 'erhe.top' |
||||||
|
self.port = 20788 |
||||||
|
self.database = 'freshrss' |
||||||
|
self.user = 'freshrss' |
||||||
|
self.password = 'freshrss' |
||||||
|
self.conn = None |
||||||
|
|
||||||
|
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}") |
||||||
|
else: |
||||||
|
print("Connected to the database successfully.") |
||||||
|
|
||||||
|
if not self.conn: |
||||||
|
raise Exception("Database connection failed") |
||||||
|
|
||||||
|
def check_and_insert(self, data): |
||||||
|
"""检查 URL 是否存在,如果不存在则插入整个数据字典""" |
||||||
|
try: |
||||||
|
with self.conn.cursor() as cursor: |
||||||
|
# 检查 URL 是否存在 |
||||||
|
select_sql = "SELECT COUNT(*) FROM freshrsstoor_feed WHERE url = %s" |
||||||
|
cursor.execute(select_sql, (data['url'],)) |
||||||
|
result = cursor.fetchone() |
||||||
|
if result[0] == 0: |
||||||
|
# URL 不存在,插入新记录 |
||||||
|
columns = ', '.join(data.keys()) |
||||||
|
values = ', '.join(['%s'] * len(data)) |
||||||
|
insert_sql = """INSERT INTO freshrsstoor_feed |
||||||
|
(url, kind, category, "name", website, description, "lastUpdate", priority, "pathEntries", "httpAuth", "error", "ttl", attributes, "cache_nbEntries", "cache_nbUnreads") |
||||||
|
VALUES ('{}', {}, {}, '{}', '{}', '{}', {}, {}, '{}', '{}', {}, {}, '{}', {}, {});""".format( |
||||||
|
data['url'], |
||||||
|
data['kind'], |
||||||
|
data['category'], |
||||||
|
data['name'], |
||||||
|
data['website'], |
||||||
|
data['description'], |
||||||
|
data['lastUpdate'], |
||||||
|
data['priority'], |
||||||
|
data['pathEntries'], |
||||||
|
data['httpAuth'], |
||||||
|
data['error'], |
||||||
|
data['ttl'], |
||||||
|
data['attributes'], |
||||||
|
data['cache_nbEntries'], |
||||||
|
data['cache_nbUnreads'] |
||||||
|
) |
||||||
|
cursor.execute(insert_sql, tuple(data.values())) |
||||||
|
self.conn.commit() |
||||||
|
print("Data inserted successfully.") |
||||||
|
else: |
||||||
|
print("URL already exists.") |
||||||
|
except Error as e: |
||||||
|
print(f"Error: {e}") |
||||||
|
finally: |
||||||
|
if self.conn is not None: |
||||||
|
self.conn.close() |
||||||
|
|
||||||
|
|
||||||
|
# 使用示例 |
||||||
|
if __name__ == "__main__": |
||||||
|
cr = CreateRssRecord() |
||||||
|
cr.connect() |
||||||
|
insert_data = { |
||||||
|
'url': 'https://rsshub.app/jike/topic/556688fae4b00c57d9dd46ee', |
||||||
|
'category': 7, |
||||||
|
'name': '今日份的摄影 - 即刻圈子', |
||||||
|
'website': 'http://finance.sina.com.cn/china/', |
||||||
|
'description': '爱摄影的即友都在这里~分享原创摄影作品,感受照片背后的共鸣吧! - Powered by RSSHub', |
||||||
|
'kind': 0, |
||||||
|
'lastUpdate': int(time.time()), |
||||||
|
'priority': 10, |
||||||
|
'pathEntries': '', |
||||||
|
'httpAuth': '', |
||||||
|
'error': 0, |
||||||
|
'ttl': 0, |
||||||
|
'attributes': '{"curl_params":null,"ssl_verify":null,"timeout":null}', |
||||||
|
'cache_nbEntries': 0, |
||||||
|
'cache_nbUnreads': 0 |
||||||
|
} |
||||||
|
cr.check_and_insert(insert_data) |
||||||
@ -0,0 +1,25 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
import aiohttp |
||||||
|
import asyncio |
||||||
|
|
||||||
|
|
||||||
|
async def fetch(url): |
||||||
|
async with aiohttp.ClientSession() as session: |
||||||
|
async with session.get(url) as response: |
||||||
|
return await response.text() |
||||||
|
|
||||||
|
|
||||||
|
async def main(): |
||||||
|
url = 'http://api.ip.cc' |
||||||
|
content = await fetch(url) |
||||||
|
print(content) |
||||||
|
|
||||||
|
|
||||||
|
asyncio.run(main()) |
||||||
|
|
||||||
|
''' |
||||||
|
Proxy server: 175.99.17.215 |
||||||
|
port: 6011 |
||||||
|
username: lumi-jiege0210 |
||||||
|
password: aaaAAA111 |
||||||
|
''' |
||||||
@ -0,0 +1,15 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
import httpx |
||||||
|
|
||||||
|
|
||||||
|
def get_public_ip(): |
||||||
|
try: |
||||||
|
# 使用 httpx 发起请求 |
||||||
|
response = httpx.get("https://httpbin.org/ip", timeout=10) |
||||||
|
response.raise_for_status() # 检查请求是否成功 |
||||||
|
ip_data = response.json() |
||||||
|
return ip_data["origin"] |
||||||
|
except httpx.RequestError as e: |
||||||
|
print(f"An error occurred while obtaining the public IP address.:{e}") |
||||||
|
exit(1) |
||||||
|
|
||||||
@ -0,0 +1,236 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
import os |
||||||
|
|
||||||
|
import requests |
||||||
|
|
||||||
|
# 青龙面板的地址 |
||||||
|
url = "https://auto.erhe.top" |
||||||
|
|
||||||
|
|
||||||
|
# 登录青龙面板 |
||||||
|
def login(): |
||||||
|
response = requests.post(f"{url}/api/user/login", json={"username": "toor", "password": "!QAZ2wsx+0913"}) |
||||||
|
print(response) |
||||||
|
if response.status_code != 200: |
||||||
|
print(response.status_code) |
||||||
|
print(response.text) |
||||||
|
exit(0) |
||||||
|
return response.json()['data']['token'] |
||||||
|
|
||||||
|
|
||||||
|
# 获取任务列表 |
||||||
|
def get_tasks(token): |
||||||
|
response = requests.get(f"{url}/api/crons", headers={"Authorization": f"Bearer {token}"}) |
||||||
|
return response.json()['data']['data'] |
||||||
|
|
||||||
|
|
||||||
|
# 创建任务 |
||||||
|
def create_task(task_template, token): |
||||||
|
payload = { |
||||||
|
"name": task_template["name"], |
||||||
|
"command": task_template["command"], |
||||||
|
"schedule": task_template["schedule"], |
||||||
|
"labels": task_template["labels"] |
||||||
|
} |
||||||
|
headers = { |
||||||
|
"Authorization": f"Bearer {token}", |
||||||
|
"Content-Type": "application/json" |
||||||
|
} |
||||||
|
response = requests.post(f"{url}/api/crons", headers=headers, json=payload) |
||||||
|
return response.json() |
||||||
|
|
||||||
|
|
||||||
|
# 创建视图分类 |
||||||
|
def create_view_type(token): |
||||||
|
view_type_list = ['base', 'spider_common'] |
||||||
|
for view_type in view_type_list: |
||||||
|
payload = { |
||||||
|
"name": view_type, |
||||||
|
"filters": { |
||||||
|
'property': 'labels', |
||||||
|
'operation': 'Reg', |
||||||
|
'value': view_type |
||||||
|
}, |
||||||
|
'filterRelation': 'and' |
||||||
|
} |
||||||
|
headers = { |
||||||
|
"Authorization": f"Bearer {token}", |
||||||
|
"Content-Type": "application/json" |
||||||
|
} |
||||||
|
response = requests.post(f"{url}/api/crons", headers=headers, json=payload) |
||||||
|
|
||||||
|
|
||||||
|
# 主逻辑 |
||||||
|
def main(): |
||||||
|
while True: |
||||||
|
try: |
||||||
|
token = login() |
||||||
|
print(f"已连接到 {url}") |
||||||
|
tasks = get_tasks(token) |
||||||
|
tasks_names = [task['name'] for task in tasks] |
||||||
|
if tasks: |
||||||
|
print("Current tasks name: \n{}, \ntotal: {}".format('\n'.join(tasks_names), str(len(tasks_names)))) |
||||||
|
else: |
||||||
|
print("Tasks list is empty") |
||||||
|
|
||||||
|
project_path = '/ql/data/scripts/auto/' |
||||||
|
base_path = os.path.join(project_path, 'base') |
||||||
|
spider_path = os.path.join(project_path, 'spider') |
||||||
|
message_path = os.path.join(project_path, 'message') |
||||||
|
manual_path = os.path.join(project_path, 'manual') |
||||||
|
daily_path = os.path.join(project_path, 'daily') |
||||||
|
tasks_template = [{ |
||||||
|
'base_tasks': [ |
||||||
|
{ |
||||||
|
"name": "每天开始自动创建日志", |
||||||
|
"command": "python3 {}/base_daily_logs_generate.py".format(base_path), |
||||||
|
"schedule": "0 0 * * *", |
||||||
|
"labels": ["base"] |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "每天结束自动发送日志", |
||||||
|
"command": "python3 {}/base_daily_logs_send.py".format(base_path), |
||||||
|
"schedule": "58 23 * * *", |
||||||
|
"labels": ["base"] |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "每天自动删除旧数据", |
||||||
|
"command": "python3 {}/base_timing_remove_data.py".format(base_path), |
||||||
|
"schedule": "1 0 * * *", |
||||||
|
"labels": ["base"] |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "每天新闻汇总,发送到邮箱", |
||||||
|
"command": "python3 {}/base_news_data_collation.py".format(base_path), |
||||||
|
"schedule": "0 10 6,12,18 * * *", |
||||||
|
"labels": ["base"] |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "定时刷新 freshrss 订阅源", |
||||||
|
"command": "python3 {}/update_feed.py".format(base_path), |
||||||
|
"schedule": "0 6,22 * * *", |
||||||
|
"labels": ["base"] |
||||||
|
} |
||||||
|
], |
||||||
|
'spider': [ |
||||||
|
{ |
||||||
|
"name": "自动执行反斗限免爬虫", |
||||||
|
"command": "python3 {}/news_get_apprcn.py".format(spider_path), |
||||||
|
"schedule": "0 0 3,6,9,12,15,18,21 * * *", |
||||||
|
"labels": ["spider"] |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "自动执行chiphell爬虫", |
||||||
|
"command": "python3 {}/news_get_chiphell.py".format(spider_path), |
||||||
|
"schedule": "0 0 3,6,9,12,15,18,21 * * *", |
||||||
|
"labels": ["spider"] |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "自动执行hello_github爬虫", |
||||||
|
"command": "python3 {}/news_get_hello_github.py".format(spider_path), |
||||||
|
"schedule": "0 0 3,6,9,12,15,18,21 * * *", |
||||||
|
"labels": ["spider"] |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "自动执行Anyknew爬虫", |
||||||
|
"command": "python3 {}/news_get_news.py".format(spider_path), |
||||||
|
"schedule": "0 0 3,6,9,12,15,18,21 * * *", |
||||||
|
"labels": ["spider"] |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "自动执行币界网文章爬虫", |
||||||
|
"command": "python3 {}/spider_web3_coin_world.py".format(spider_path), |
||||||
|
"schedule": "0 0 3,6,9,12,15,18,21 * * *", |
||||||
|
"labels": ["spider"] |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "获取 web3 新闻", |
||||||
|
"command": "python3 {}/spider_web3_news.py".format(spider_path), |
||||||
|
"schedule": "0 0 3,6,9,12,15,18,21 * * *", |
||||||
|
"labels": ["spider"] |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "自动执行dlt爬虫", |
||||||
|
"command": "python3 {}/spider_get_and_check_dlt.py".format(spider_path), |
||||||
|
"schedule": "30 22 * * 1,3,6", |
||||||
|
"labels": ["spider"] |
||||||
|
} |
||||||
|
], |
||||||
|
'message_tasks': [ |
||||||
|
{ |
||||||
|
"name": "获取coin实时数据", |
||||||
|
"command": "python3 {}/message_coin_detail.py".format(message_path), |
||||||
|
"schedule": "0 * * * *", |
||||||
|
"labels": ["message"] |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "对比大乐透最新一期数据,匹配已购买号码,发送消息", |
||||||
|
"command": "python3 {}/message_dlt.py".format(message_path), |
||||||
|
"schedule": "30 22 * * 1,3,6", |
||||||
|
"labels": ["message"] |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "获取未来 7 天的天气预报", |
||||||
|
"command": "python3 {}/message_get_one_week_weather.py".format(message_path), |
||||||
|
"schedule": "0 0 6,22 * * *", |
||||||
|
"labels": ["message"] |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "从 freshrss-psql 数据库中读取数据并发送", |
||||||
|
"command": "python3 {}/message_rss_data_handel.py".format(message_path), |
||||||
|
"schedule": "30 6,9,12,18,22 * * *", |
||||||
|
"labels": ["message"] |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "空投任务消息", |
||||||
|
"command": "python3 {}/message_airdrop_tasks.py".format(message_path), |
||||||
|
"schedule": "0 8,20 * * *", |
||||||
|
"labels": ["message"] |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "链捕手快讯消息推送", |
||||||
|
"command": "python3 {}/message_chaincatcher.py".format(message_path), |
||||||
|
"schedule": "0 */2 * * *", |
||||||
|
"labels": ["message"] |
||||||
|
} |
||||||
|
], |
||||||
|
'manual': [ |
||||||
|
{ |
||||||
|
"name": "手动读取rss订阅新闻", |
||||||
|
"command": "python3 {}/read_news.py".format(manual_path), |
||||||
|
"schedule": "0 0 1 1 *", |
||||||
|
"labels": ["manual"] |
||||||
|
} |
||||||
|
], |
||||||
|
'daily': [ |
||||||
|
{ |
||||||
|
"name": "3dos自动签到", |
||||||
|
"command": "python3 {}/daily_3dos.py".format(daily_path), |
||||||
|
"schedule": "*/5 * * * *", |
||||||
|
"labels": ["daily"] |
||||||
|
} |
||||||
|
], |
||||||
|
}] |
||||||
|
|
||||||
|
for task_template in tasks_template: |
||||||
|
for task_type, task_list in task_template.items(): |
||||||
|
for task in task_list: |
||||||
|
task_name = task["name"] |
||||||
|
if task_name in tasks_names: |
||||||
|
print("Task {} already exists.".format(task_name)) |
||||||
|
else: |
||||||
|
result = create_task(task, token) |
||||||
|
print("Task creation result:", result) |
||||||
|
|
||||||
|
# 创建所有任务之后, 创建视图分类 |
||||||
|
# create_view_type(token) |
||||||
|
break # 正常执行完成后退出循环 |
||||||
|
|
||||||
|
except Exception as e: |
||||||
|
print("An error occurred: ", e) |
||||||
|
print("Retrying...") |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
main() |
||||||
|
print('done!') |
||||||
@ -0,0 +1,58 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
|
||||||
|
import httpx |
||||||
|
|
||||||
|
|
||||||
|
class GotifyNotifier: |
||||||
|
def __init__(self, title, message, token_name=''): |
||||||
|
self.gotify_url = 'https://gotify.erhe.top' |
||||||
|
self.app_token = self.match_token_name(token_name) |
||||||
|
self.title = title |
||||||
|
self.message = message |
||||||
|
|
||||||
|
def match_token_name(self, name): |
||||||
|
token_name_dict = { |
||||||
|
'base': 'A8EVb0Cmxnb2vfk', |
||||||
|
'coin': 'AgfOJESqDKftBTQ', |
||||||
|
'dlt': 'A3bqt9Dlbs.fPUb', |
||||||
|
'AirdropTasksNews': 'Aoe0VKt-kkZnm8d', |
||||||
|
'weather': 'A9KF--mx_12PjSu', |
||||||
|
'news': 'AT2QGp_vyCX4akW', |
||||||
|
'CheckAndRemind': 'Aw7XKE2Ppk7Dgwk', |
||||||
|
'test': 'A0Xg6ZE5946iBYg', |
||||||
|
} |
||||||
|
|
||||||
|
token = token_name_dict.get(name) |
||||||
|
if token: |
||||||
|
return token |
||||||
|
else: |
||||||
|
return token_name_dict['base'] |
||||||
|
|
||||||
|
def send_message(self): |
||||||
|
# 构建POST请求的headers |
||||||
|
headers = { |
||||||
|
'Content-Type': 'application/json' |
||||||
|
} |
||||||
|
|
||||||
|
# 构建POST请求的body |
||||||
|
body = { |
||||||
|
'title': self.title, |
||||||
|
'message': self.message |
||||||
|
} |
||||||
|
|
||||||
|
# 发送POST请求 |
||||||
|
with httpx.Client() as client: |
||||||
|
response = client.post( |
||||||
|
url=f"{self.gotify_url}/message?token={self.app_token}", |
||||||
|
headers=headers, |
||||||
|
json=body |
||||||
|
) |
||||||
|
|
||||||
|
# 或者可以使用 curl |
||||||
|
# curl -k "https://gotify.erhe.top/message?token=A0Xg6ZE5946iBYg" -F "title=测试发送信息" -F "message=假装有信息,测试发送" -F "priority=5" |
||||||
|
|
||||||
|
# 检查响应状态码 |
||||||
|
if response.status_code == 200: |
||||||
|
print('Gotify Message sent successfully!') |
||||||
|
else: |
||||||
|
print('Failed to send message:', response.text) |
||||||
@ -0,0 +1,109 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
import re |
||||||
|
|
||||||
|
import httpx |
||||||
|
import asyncio |
||||||
|
import json |
||||||
|
import random |
||||||
|
import logging |
||||||
|
from typing import List |
||||||
|
from fake_useragent import UserAgent # 导入 fake_useragent 模块 |
||||||
|
|
||||||
|
# 配置日志 |
||||||
|
logging.basicConfig( |
||||||
|
level=logging.INFO, |
||||||
|
format='%(asctime)s - %(levelname)s - %(message)s' |
||||||
|
) |
||||||
|
logger = logging.getLogger(__name__) |
||||||
|
|
||||||
|
# 初始化 fake_useragent |
||||||
|
ua = UserAgent() |
||||||
|
|
||||||
|
|
||||||
|
async def send_post_request(wallet: str, timeout: float = 10.0) -> None: |
||||||
|
""" |
||||||
|
向目标网站发送 POST 请求以领取水。 |
||||||
|
|
||||||
|
Args: |
||||||
|
wallet: 钱包地址 |
||||||
|
timeout: 请求超时时间(秒) |
||||||
|
""" |
||||||
|
url = "https://faucet.nerzo.xyz/monad" |
||||||
|
|
||||||
|
headers = { |
||||||
|
"accept": "text/x-component", |
||||||
|
"accept-encoding": "gzip, deflate, br, zstd", |
||||||
|
"accept-language": "zh-CN,zh;q=0.9", |
||||||
|
"content-type": "text/plain;charset=UTF-8", |
||||||
|
"next-action": "405d6e23437f844564e65cdd65851724c449d7f778", |
||||||
|
"next-router-state-tree": '["",{"children":["(faucet)",{"children":["monad",{"children":["__PAGE__",{},"/monad","refresh"]}]}]},null,null,true]', |
||||||
|
"origin": "https://faucet.nerzo.xyz", |
||||||
|
"priority": "u=1, i", |
||||||
|
"referer": "https://faucet.nerzo.xyz/monad", |
||||||
|
"sec-ch-ua": '"Chromium";v="130", "Google Chrome";v="130", "Not?A_Brand";v="99"', |
||||||
|
"sec-ch-ua-mobile": "?0", |
||||||
|
"sec-ch-ua-platform": '"Windows"', |
||||||
|
"sec-fetch-dest": "empty", |
||||||
|
"sec-fetch-mode": "cors", |
||||||
|
"sec-fetch-site": "same-origin", |
||||||
|
"user-agent": ua.random, |
||||||
|
"x-deployment-id": "dpl_DWgqqeB8V4ASD1aCKUqWZwcPwnVd" |
||||||
|
} |
||||||
|
payload = json.dumps([wallet]) |
||||||
|
|
||||||
|
async with httpx.AsyncClient(timeout=timeout, proxy={'http://': 'http://127.0.0.1:7890'}) as client: |
||||||
|
retry = 3 |
||||||
|
while retry > 0: # 修复了 retry 的逻辑错误 |
||||||
|
try: |
||||||
|
response = await client.post(url, headers=headers, content=payload) |
||||||
|
# logger.info(f"Wallet: {wallet} | Status Code: {response.status_code} | Response: {response.text}") |
||||||
|
logger.info(f"Wallet: {wallet} | Status Code: {response.status_code}") |
||||||
|
if 'message' in response.text: |
||||||
|
message = re.findall(r'"message":"(.*?)"', response.text)[0] |
||||||
|
logger.info(f"Wallet: {wallet} | Message: {message}") |
||||||
|
return response |
||||||
|
except httpx.RequestError as e: |
||||||
|
logger.error(f"Wallet: {wallet} | Request failed: {e}") |
||||||
|
retry -= 1 |
||||||
|
|
||||||
|
if retry <= 0: |
||||||
|
return None |
||||||
|
|
||||||
|
|
||||||
|
async def main(wallet_list: List[str], min_delay: float = 5.0, max_delay: float = 8.0) -> None: |
||||||
|
""" |
||||||
|
批量处理钱包地址,发送 POST 请求,并添加随机延时。 |
||||||
|
|
||||||
|
Args: |
||||||
|
wallet_list: 钱包地址列表 |
||||||
|
min_delay: 最小延时(秒) |
||||||
|
max_delay: 最大延时(秒) |
||||||
|
""" |
||||||
|
for i, wallet in enumerate(wallet_list, 1): |
||||||
|
logger.info(f"Processing wallet {i}/{len(wallet_list)}: {wallet}") |
||||||
|
await send_post_request(wallet) |
||||||
|
# 在最后一个钱包之前添加随机延时 |
||||||
|
if i < len(wallet_list): |
||||||
|
delay = random.uniform(min_delay, max_delay) |
||||||
|
logger.info(f"Waiting for {delay:.2f} seconds before next request") |
||||||
|
await asyncio.sleep(delay) |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
wallet_list = [ |
||||||
|
'0xe50B77Cd771243b8Ae1d6ce33b4E13ECC5Fa28a6', |
||||||
|
'0x9ea2ECAD4090E32916e03b77d7C75CbF6C8E0A55', |
||||||
|
'0xE8A4b0C04300154DC9B1D0e565Ba70F996614690', |
||||||
|
'0x1b623c5d70c93b437d93c305bf2cfa389095f636', |
||||||
|
'0x06D25c3e0E1F753ac0486a3f8aaD7259149656cB', |
||||||
|
'0x15cFEE34Ca4541CAc9a1c4B6F6aB47A65877E240', |
||||||
|
'0x7aBF0dA8Ac07B6dE7206e467988455E1AD0b60B5', |
||||||
|
'0xF736f45d4663a8D8DfF7EFA55b1Cf6Fe38D026c8', |
||||||
|
'0x83173eECf3a6d9ABB79682568e16c2eAd361620e', |
||||||
|
'0xa401b85B4849Fc7610Bd180cc937859C78528F47', |
||||||
|
'0x10A43E7Fe77E2D84adBeC26cF0bFc6f403841266', |
||||||
|
'0x70D5EE1DfddD3726f0D71F4CD5a8Ef43aC651a75' |
||||||
|
] |
||||||
|
random.shuffle(wallet_list) |
||||||
|
asyncio.run(main(wallet_list)) |
||||||
|
print("done") |
||||||
Loading…
Reference in new issue