This commit is contained in:
sansenhoshi
2026-01-04 17:15:40 +08:00
commit 275f05ee4a
207 changed files with 12305 additions and 0 deletions
@@ -0,0 +1,245 @@
import random
import time
import httpx
import asyncio
import io
import json
import os
import re
from nonebot import logger
from io import BytesIO
from datetime import datetime
from PIL import Image, ImageOps, ImageDraw, ImageFont
from nonebot.internal.params import ArgPlainText
from nonebot.typing import T_State
from playwright.async_api import async_playwright
from nonebot import on_command
from nonebot.adapters.onebot.v11 import MessageEvent, Bot, MessageSegment
from nonebot.plugin import PluginMetadata
from typing import Optional, Union
from .utils import *
from nonebot.matcher import Matcher
__plugin_meta__ = PluginMetadata(
name="绝地潜兵小助手",
description="绝地潜兵小助手,提供一些小功能,让超级地球更加美好!",
usage="简报:获取星系战争简要概况\n"
"随机战备:让机器人帮你随机一套战备",
type="application",
homepage="https://github.com/sansenhoshi/nonebot_plugin_helldivers_tools"
)
basic_path = os.path.dirname(__file__)
save_path = os.path.join(basic_path, "temp")
img_path = os.path.join(basic_path, "img")
data_path = os.path.join(basic_path, "data")
war_situation = on_command("简报", aliases={"简报"})
se_situation = on_command("超级地球战况", aliases={"超级地球战况"})
@war_situation.handle()
async def get_war_info(ev: MessageEvent):
await war_situation.send("正在获取前线战况……\n本地化需要30s左右,请民主的等待")
url1 = r"https://hd2galaxy.com/"
url2 = r"https://helldiverscompanion.com/#"
url3 = r"https://helldiverscompanion.com/#hellpad/planets/super_earth/regions"
time_present1 = get_present_time()
result = await screen_shot(url2, time_present1)
if result != "success":
await war_situation.finish(MessageSegment.reply(ev.message_id) + result)
img_path1 = os.path.join(save_path, f"{time_present1}.png")
logger.info(img_path1)
images = gen_ms_img(Image.open(img_path1))
mes = (MessageSegment.reply(ev.message_id), images)
await war_situation.send(mes)
os.remove(img_path1)
@se_situation.handle()
async def get_se_info(ev: MessageEvent):
await war_situation.send("正在获取……\n本地化需要30s左右,请民主的等待")
url1 = r"https://hd2galaxy.com/"
url2 = r"https://helldiverscompanion.com/#"
url3 = r"https://helldiverscompanion.com/#hellpad/planets/super_earth/regions"
time_present1 = get_present_time()
result = await screen_shot_2(url3, time_present1)
if result != "success":
await war_situation.finish(MessageSegment.reply(ev.message_id) + result)
img_path1 = os.path.join(save_path, f"{time_present1}.png")
logger.info(img_path1)
images = gen_ms_img(Image.open(img_path1))
mes = (MessageSegment.reply(ev.message_id), images)
await war_situation.send(mes)
os.remove(img_path1)
async def download_url(url: str) -> bytes:
async with httpx.AsyncClient() as client:
for i in range(3):
try:
resp = await client.get(url)
if resp.status_code != 200:
continue
return resp.content
except Exception as e:
print(f"Error downloading {url}, retry {i}/3: {str(e)}")
random_helldivers = on_command("随机战备", aliases={"随机战备"}, block=True)
PROMPT = """ ***超级地球武装部***
请发送你需要的随机规则
1:纯随机(不推荐)
套路随机(按一定规则随机)
22红/1蓝/1绿
32绿/1红/1蓝
42蓝/1绿/1红
53红/1蓝
63绿/1蓝
72红/2蓝
82蓝/2绿
92绿/2红
104红
114绿"""
@random_helldivers.got("pick_type", prompt=PROMPT)
# 用户选择
async def got_random_helldivers(event: MessageEvent, pick_type: str = ArgPlainText()):
logger.info(f"用户选择的战备类型: {pick_type}")
if not is_number(pick_type):
await random_helldivers.reject(f"您输入的 {pick_type} 非数字,请重新输入1到11,或者输入0退出")
elif int(pick_type) not in range(12):
await random_helldivers.reject(f"您输入的 {pick_type} 不在范围内,请重新输入1到11,或者输入0退出")
elif int(pick_type) == 0:
logger.info("用户选择退出随机战备")
return
mix_msg = (MessageSegment.reply(event.message_id),)
type_combinations = {
2: {'red': 2, 'blue': 1, 'green': 1},
3: {'green': 2, 'red': 1, 'blue': 1},
4: {'blue': 2, 'green': 1, 'red': 1},
5: {'red': 3, 'blue': 1},
6: {'green': 3, 'blue': 1},
7: {'red': 2, 'blue': 2},
8: {'blue': 2, 'green': 2},
9: {'green': 2, 'red': 2},
10: {'red': 4},
11: {'green': 4}
}
if int(pick_type) == 1:
logger.info("用户选择纯随机战备")
result = await get_random_equipment(4) # 4 random equipments
else:
combination = type_combinations.get(int(pick_type))
logger.info(f"用户选择的战备组合: {combination}")
result = await get_equipment_by_combination(combination)
final_msg = MessageSegment.text("您的随机结果是:\n")
img_base_str = pic2b64(Image.open(result))
image_turple = MessageSegment.image(img_base_str)
mix_msg += (final_msg, image_turple)
await random_helldivers.finish(mix_msg)
async def get_random_equipment(count):
data_config = os.path.join(basic_path, "data")
with open(data_config + "/equipment.json", "r", encoding="utf-8") as file:
data = json.load(file)
indices = select_random_equipment(len(data), count)
selected_equipment = [data[i] for i in indices]
return create_image(selected_equipment)
async def get_equipment_by_combination(type_combination):
data_config = os.path.join(basic_path, "data")
with open(data_config + "/equipment.json", "r", encoding="utf-8") as file:
data = json.load(file)
equipment_by_type = categorize_equipment_by_type(data)
selected_equipment = select_equipment_by_type(equipment_by_type, type_combination)
logger.debug(f"根据组合选择的装备: {selected_equipment}")
return create_image(selected_equipment)
def categorize_equipment_by_type(data):
equipment_by_type = {}
for item in data:
equip_type = item['type']
if equip_type not in equipment_by_type:
equipment_by_type[equip_type] = []
equipment_by_type[equip_type].append(item)
return equipment_by_type
def select_equipment_by_type(equipment_by_type, type_combination):
selected_equipment = []
backpack_count = 0
for equip_type, count in type_combination.items():
if equip_type in equipment_by_type:
available_items = equipment_by_type[equip_type]
random.shuffle(available_items)
selected = 0
for item in available_items:
if selected < count:
if item['backpack'] == 1 and backpack_count >= 1:
continue
selected_equipment.append(item)
selected += 1
if item['backpack'] == 1:
backpack_count += 1
else:
break
return selected_equipment
def select_random_equipment(max_equipment, count):
return random.sample(range(max_equipment), count)
def create_image(selected_equipment):
new_img = Image.new('RGBA', (800, 500), (0, 0, 0, 1000))
logo_path = img_path + "/super earth.png"
logo = Image.open(logo_path)
new_img = image_paste(logo, new_img, (682, 20))
draw = ImageDraw.Draw(new_img)
ch_text_font = ImageFont.truetype(data_path + '/font/msyh.ttc', 36)
pos_horizon = 20
for equipment in selected_equipment:
name = equipment['name']
path = basic_path + "/" + equipment['path'].replace("\\", "/")
icon = Image.open(path)
icon = icon.resize((100, 100))
new_img = image_paste(icon, new_img, (20, pos_horizon))
draw.text((140, pos_horizon + 5), '战备名称:', fill='white', font=ch_text_font)
draw.text((140, pos_horizon + 50), f'{name}', fill='white', font=ch_text_font)
pos_horizon += 120
b_io = BytesIO()
new_img = ImageOps.expand(new_img, border=10, fill="white")
new_img.save(b_io, format="PNG")
return b_io
def image_paste(paste_image, under_image, pos):
if paste_image.mode == 'RGBA':
under_image.paste(paste_image, pos, mask=paste_image.split()[3])
else:
under_image.paste(paste_image, pos)
return under_image
def is_number(s):
return bool(re.match(r'^[0-9]+$', s))
@@ -0,0 +1,374 @@
[
{
"name": "A-G-16 加特林哨戒炮",
"path": "img/helldivers/A-G-16 加特林哨戒炮.png",
"type": "green",
"backpack": 0
},
{
"name": "A-M-23 电磁冲击波迫击哨戒炮",
"path": "img/helldivers/A-M-23 电磁冲击波迫击哨戒炮.png",
"type": "green",
"backpack": 0
},
{
"name": "A-MG-43 哨戒机枪",
"path": "img/helldivers/A-MG-43 哨戒机枪.png",
"type": "green",
"backpack": 0
},
{
"name": "A-MLS-4X 火箭哨戒炮",
"path": "img/helldivers/A-MLS-4X 火箭哨戒炮.png",
"type": "green",
"backpack": 0
},
{
"name": "AAC-8 自动哨戒炮",
"path": "img/helldivers/AAC-8 自动哨戒炮.png",
"type": "green",
"backpack": 0
},
{
"name": "AARC-3 特斯拉塔",
"path": "img/helldivers/AARC-3 特斯拉塔.png",
"type": "green",
"backpack": 0
},
{
"name": "AC-8 机炮",
"path": "img/helldivers/AC-8 机炮.png",
"type": "blue",
"backpack": 1
},
{
"name": "AM-12 迫击哨戒炮",
"path": "img/helldivers/AM-12 迫击哨戒炮.png",
"type": "green",
"backpack": 0
},
{
"name": "APW-1 反器材步枪",
"path": "img/helldivers/APW-1 反器材步枪.png",
"type": "blue",
"backpack": 0
},
{
"name": "ARC-3 电弧发射器",
"path": "img/helldivers/ARC-3 电弧发射器.png",
"type": "blue",
"backpack": 0
},
{
"name": "AX-AR-3 护卫犬",
"path": "img/helldivers/AX-AR-3 护卫犬.png",
"type": "blue",
"backpack": 1
},
{
"name": "AX-LAS-5 护卫犬漫游车",
"path": "img/helldivers/AX-LAS-5 护卫犬漫游车.png",
"type": "blue",
"backpack": 1
},
{
"name": "B-1 补给背包",
"path": "img/helldivers/B-1 补给背包.png",
"type": "blue",
"backpack": 1
},
{
"name": "E-MG-101 重机枪部署支架",
"path": "img/helldivers/E-MG-101 重机枪部署支架.png",
"type": "green",
"backpack": 0
},
{
"name": "EAT-17 消耗性反坦克武器",
"path": "img/helldivers/EAT-17 消耗性反坦克武器.png",
"type": "blue",
"backpack": 0
},
{
"name": "FAF-14 飞矛",
"path": "img/helldivers/FAF-14 飞矛.png",
"type": "blue",
"backpack": 1
},
{
"name": "FLAM-40 火焰喷射器",
"path": "img/helldivers/FLAM-40 火焰喷射器.png",
"type": "blue",
"backpack": 0
},
{
"name": "FX-12 防护罩生成中继器",
"path": "img/helldivers/FX-12 防护罩生成中继器.png",
"type": "green",
"backpack": 0
},
{
"name": "GL-21 榴弹发射器",
"path": "img/helldivers/GL-21 榴弹发射器.png",
"type": "blue",
"backpack": 0
},
{
"name": "GR-8 无后座力炮",
"path": "img/helldivers/GR-8 无后座力炮.png",
"type": "blue",
"backpack": 1
},
{
"name": "LAS-98 激光大炮",
"path": "img/helldivers/LAS-98 激光大炮.png",
"type": "blue",
"backpack": 0
},
{
"name": "LAS-99 类星体加农炮",
"path": "img/helldivers/LAS-99 类星体加农炮.png",
"type": "blue",
"backpack": 0
},
{
"name": "LIFT-850 喷射背包",
"path": "img/helldivers/LIFT-850 喷射背包.png",
"type": "blue",
"backpack": 1
},
{
"name": "M-105 盟友",
"path": "img/helldivers/M-105 盟友.png",
"type": "blue",
"backpack": 0
},
{
"name": "MD-14 燃烧地雷",
"path": "img/helldivers/MD-14 燃烧地雷.png",
"type": "green",
"backpack": 0
},
{
"name": "MD-6 反步兵雷区",
"path": "img/helldivers/MD-6 反步兵雷区.png",
"type": "green",
"backpack": 0
},
{
"name": "MG-43 机枪",
"path": "img/helldivers/MG-43 机枪.png",
"type": "blue",
"backpack": 0
},
{
"name": "RS-422 磁轨炮",
"path": "img/helldivers/RS-422 磁轨炮.png",
"type": "blue",
"backpack": 0
},
{
"name": "SH-20 防弹护盾背包",
"path": "img/helldivers/SH-20 防弹护盾背包.png",
"type": "blue",
"backpack": 1
},
{
"name": "SH-32 防护罩生成包",
"path": "img/helldivers/SH-32 防护罩生成包.png",
"type": "blue",
"backpack": 1
},
{
"name": "EXO-45 爱国者外骨骼装甲",
"path": "img/helldivers/EXO-45 爱国者外骨骼装甲.png",
"type": "blue",
"backpack": 0
},
{
"name": "轨道120MM高爆弹火力网",
"path": "img/helldivers/轨道120MM高爆弹火力网.png",
"type": "red",
"backpack": 0
},
{
"name": "轨道380MM高爆弹火力网",
"path": "img/helldivers/轨道380MM高爆弹火力网.png",
"type": "red",
"backpack": 0
},
{
"name": "轨道加特林火力网",
"path": "img/helldivers/轨道加特林火力网.png",
"type": "red",
"backpack": 0
},
{
"name": "轨道毒气攻击",
"path": "img/helldivers/轨道毒气攻击.png",
"type": "red",
"backpack": 0
},
{
"name": "轨道游走火力网",
"path": "img/helldivers/轨道游走火力网.png",
"type": "red",
"backpack": 0
},
{
"name": "轨道激光炮",
"path": "img/helldivers/轨道激光炮.png",
"type": "red",
"backpack": 0
},
{
"name": "轨道炮攻击",
"path": "img/helldivers/轨道炮攻击.png",
"type": "red",
"backpack": 0
},
{
"name": "轨道炮精准攻击",
"path": "img/helldivers/轨道炮精准攻击.png",
"type": "red",
"backpack": 0
},
{
"name": "轨道烟雾攻击",
"path": "img/helldivers/轨道烟雾攻击.png",
"type": "red",
"backpack": 0
},
{
"name": "轨道电磁冲击波攻击",
"path": "img/helldivers/轨道电磁冲击波攻击.png",
"type": "red",
"backpack": 0
},
{
"name": "轨道空爆攻击",
"path": "img/helldivers/轨道空爆攻击.png",
"type": "red",
"backpack": 0
},
{
"name": "重机枪",
"path": "img/helldivers/重机枪.png",
"type": "bule",
"backpack": 0
},
{
"name": "飞鹰110MM火箭巢",
"path": "img/helldivers/飞鹰110MM火箭巢.png",
"type": "red",
"backpack": 0
},
{
"name": "飞鹰500KG炸弹",
"path": "img/helldivers/飞鹰500KG炸弹.png",
"type": "red",
"backpack": 0
},
{
"name": "飞鹰凝固汽油弹空袭",
"path": "img/helldivers/飞鹰凝固汽油弹空袭.png",
"type": "red",
"backpack": 0
},
{
"name": "飞鹰机枪扫射",
"path": "img/helldivers/飞鹰机枪扫射.png",
"type": "red",
"backpack": 0
},
{
"name": "飞鹰烟雾攻击",
"path": "img/helldivers/飞鹰烟雾攻击.png",
"type": "red",
"backpack": 0
},
{
"name": "飞鹰空袭",
"path": "img/helldivers/飞鹰空袭.png",
"type": "red",
"backpack": 0
},
{
"name": "飞鹰集束炸弹",
"path": "img/helldivers/飞鹰集束炸弹.png",
"type": "red",
"backpack": 0
},
{
"name": "AX-TX-13 护卫犬腐息",
"path": "img/helldivers/AX-TX-13 护卫犬腐息.png",
"type": "blue",
"backpack": 1
},
{
"name": "EXO-49 解放者外骨骼装甲",
"path": "img/helldivers/EXO-49 解放者外骨骼装甲.png",
"type": "blue",
"backpack": 0
},
{
"name": "TX-41 灭菌器",
"path": "img/helldivers/TX-41 灭菌器.png",
"type": "blue",
"backpack": 0
},
{
"name": "轨道燃烧火力网",
"path": "img/helldivers/轨道燃烧火力网.png",
"type": "red",
"backpack": 0
},
{
"name": "MD-17 反坦克地雷",
"path": "img/helldivers/MD-17 反坦克地雷.png",
"type": "green",
"backpack": 0
},
{
"name": "MLS-4X 突击兵",
"path": "img/helldivers/MLS-4X 突击兵.png",
"type": "blue",
"backpack": 0
},
{
"name": "RL-77 空爆火箭发射器",
"path": "img/helldivers/RL-77 空爆火箭发射器.png",
"type": "blue",
"backpack": 1
},
{
"name": "A-FLAM-40 火焰喷射哨戒炮",
"path": "img/helldivers/A-FLAM-40 火焰喷射哨戒炮.png",
"type": "green",
"backpack": 0
},
{
"name": "E-AT-12 反坦克炮台",
"path": "img/helldivers/E-AT-12 反坦克炮台.png",
"type": "green",
"backpack": 0
},
{
"name": "M-102 快速侦查载具",
"path": "img/helldivers/M-102 快速侦查载具.png",
"type": "blue",
"backpack": 0
},
{
"name": "SH-51 定向护盾",
"path": "img/helldivers/SH-51 定向护盾.png",
"type": "blue",
"backpack": 1
},
{
"name": "StA-X3 W.A.S.P. Launcher",
"path": "img/helldivers/StA-X3 W.A.S.P. Launcher.png",
"type": "blue",
"backpack": 1
}
]
@@ -0,0 +1,549 @@
{
"ACTIVE PLANETS": "活跃行星",
"AWAITING MAJOR ORDER": "等待重要指令",
"TOTAL PLAYERS:": "玩家总数:",
"Stand by for further orders from Super Earth High Command": "等待超级地球最高指挥部下发重要指令",
"Major Order ends in:": "重要指令结束时间:",
"MAJOR ORDER": "重要指令",
"Defended Planets": "防守星球",
"MEDALS": "奖章",
"DEFENSE": "防守",
"INCOMING SQUID INVASION": "光能入侵!",
"MEGA CITY": "超级城市",
"INVASION": "入侵",
"LIBERATION": "解放",
"DEFENDED": "抵御进度",
"PROTECTED": "防守进度",
"LIBERATED": "解放进度",
"RESTRICTED ZONE": "管制区",
"HOLDING FOR REINFORCEMENT": "等待增援",
"ACCUMULATED": "累积量",
"Galaxy Stats": "星系状态",
"CONTROLLED": "已控制",
"EQUALITY-ON-SEA": "仰齐滨",
"REMEMBRANCE": "缅城",
"EAGLEOPOLIS": "鹰都",
"YORK SUPREME": "棒约克",
"ADMINISTRATIVE CENTER 02": "行政中心02",
"PORT MERCY": "馨加泊",
"PROSPERITY CITY": "荣城",
"Oshaune": "欧绍恩",
"Martale": "玛尔特",
"Hellmire": "海尔迈尔",
"Matar Bay": "玛塔",
"Penta": "彭塔",
"Estanu": "伊斯塔努",
"Choohe": "丘伊",
"Chort Bay": "雀特湾",
"Fori Prime": "佛里主星",
"Super Earth": "超级地球",
"Marfark": "玛尔法克",
"Crimsica": "克里姆西卡",
"Menkent": "库楼三",
"Lesath": "尾宿八",
"Vernen Wells": "佛农井",
"Nivel 43": "尼维尔43",
"Durgen": "德尔根",
"Tibit": "提比特",
"Draupnir": "德罗普尼尔",
"Malevelon Creek": "麦拉芬蒙河",
"Maia": "昂宿四",
"Fenrir III": "芬里尔III",
"Errata Prime": "艾拉特主星",
"Troost": "特鲁斯特",
"Ustotu": "伍斯特图",
"Turing": "图灵",
"Angel's Venture": "天使投资",
"Ingmar": "英格玛",
"Tien Kwan": "天关",
"Ubanea": "乌巴尼亚",
"Vandalon IV": "万达隆IV",
"Meridia": "默里迪亚",
"Veld": "维尔德",
"Mantes": "蒙特斯",
"Klen Dahth II": "克伦达斯II",
"Pathfinder V": "开拓者V",
"Widow's Harbor": "寡妇港",
"New Haven": "纽黑文",
"Pilen V": "皮伦V",
"Hydrofall Prime": "水瀑主星",
"Zea Rugosia": "泽亚鲁戈西亚",
"Darrowsport": "达罗斯波特",
"Fornskogur II": "福恩斯科古尔",
"Midasburg": "弥达斯堡",
"Cerberus IIIc": "刻耳帕洛斯IIIc",
"Prosperity Falls": "繁荣瀑布",
"Okul VI": "欧库VI",
"Martyr's Bay": "烈士湾",
"Freedom Peak": "弗里敦峰",
"Fort Union": "联合堡",
"Kelvinor": "开尔文奥尔",
"Wraith": "幽灵",
"Igla": "伊格勒",
"New Kiruna": "新基鲁纳",
"Fort Justice": "正义堡",
"Zegema Paradise": "泽格马乐土",
"Providence": "普罗维登斯",
"Primordia": "普莱默迪亚",
"Sulfura": "萨尔弗拉",
"Nublaria I": "努布拉里亚I",
"Krakatwo": "克拉克图",
"Volterra": "沃尔泰拉",
"Crucible": "熔炉",
"Veil": "帷幕",
"Marre IV": "马尔IV",
"Fort Sanctuary": "庇护堡",
"Seyshel Beach": "塞舌尔海滩",
"Effluvia": "艾芙鲁维亚",
"Solghast": "索尔加斯特",
"Dilvuia": "迪卢维亚",
"Viridia Prime": "维尔伊迪主星",
"Obari": "欧巴里",
"Myradesh": "米拉戴什",
"Atrama": "阿特拉玛",
"Emeria": "埃梅里亚",
"Barabos": "巴勒博斯",
"Fenmire": "范迈尔",
"Mastia": "玛斯蒂亚",
"Shallus": "沙勒斯",
"Krakabos": "克拉克博斯",
"Iridica": "艾丽迪卡",
"Azterra": "艾孜泰拉",
"Azur Secundus": "艾热尔次星",
"Ivis": "艾维斯",
"Slif": "斯利夫",
"Caramoor": "开勒莫尔",
"Kharst": "喀斯特",
"Eukoria": "欧科里亚",
"Myrium": "梅里翁",
"Kerth Secundus": "克斯次星",
"Parsh": "帕尔什",
"Reaf": "利夫",
"Irulta": "艾鲁尔塔",
"Emorath": "艾莫拉斯",
"Ilduna Prime": "伊尔都纳主星",
"Maw": "深渊",
"Borea": "博瑞亚",
"Curia": "居里亚",
"Tarsh": "塔尔什",
"Shelt": "谢尔特",
"Imber": "因博尔",
"Blistica": "布里斯提卡",
"Ratch": "拉奇",
"Julheim": "尤尔海姆",
"Valgaard": "瓦尔加德",
"Arkturus": "阿克图勒斯",
"Esker": "艾斯克尔",
"Terrek": "泰雷克",
"Cirrus": "希勒斯",
"Heeth": "希斯",
"Alta V": "奥尔塔V",
"Ursica XI": "厄西卡XI",
"Inari": "伊纳里",
"Skaash": "斯卡什",
"Moradesh": "莫拉戴什",
"Rasp": "拉斯普",
"Bashyr": "巴希尔",
"Regnus": "雷格努斯",
"Mog": "莫格",
"Valmox": "瓦尔莫克斯",
"Iro": "伊罗",
"Grafmere": "格拉夫米尔",
"New Stockholm": "新斯德哥尔摩",
"Oasis": "绿洲",
"Genesis Prime": "创世主星",
"Outpost 32": "32号哨站",
"Calypso": "卡利普索",
"Elysian Meadows": "埃律西昂草原",
"Alderidge Cove": "阿尔德里奇湾",
"Trandor": "特兰道尔",
"East Iridium Trading Bay": "东铱贸易湾",
"Liberty Ridge": "解放岭",
"Baldrick Prime": "巴尔德里克主星",
"The Weir": "维尔",
"Kuper": "库珀",
"Oslo Station": "奥斯陆站",
"Pöpli IX": "珀普利IX",
"Gunvald": "古恩瓦尔德",
"Dolph": "多尔夫",
"Bekvam III": "贝克温III",
"Duma Tyr": "杜马提尔",
"Aeris Pass": "亚萨关隘",
"Aurora Bay": "极光湾",
"Gaellivare": "耶利瓦勒",
"Vog-Sojoth": "佛戈索约斯",
"Kirrik": "基里克",
"Mortax Prime": "摩尔塔克斯主星",
"Wilford Station": "威尔福德站",
"Pioneer II": "先驱II",
"Erson Sands": "厄尔森桑兹",
"Socorro III": "索科罗III",
"Bore Rock": "博尔岩",
"Darius II": "大流士II",
"Acamar IV": "天园六IV",
"Achernar Secundus": "水委一次星",
"Achird III": "王良三III",
"Acrab XI": "房宿四XI",
"Acrux IX": "十字架二IX",
"Acubens Prime": "柳宿增三主星",
"Adhara": "弧矢七",
"Afoyay Bay": "艾福亚湾",
"Alairt III": "艾列尔特III",
"Alamak VII": "天大将军——VII",
"Alaraph": "右执法",
"Alathfar XI": "织女增三XI",
"Andar": "安达尔",
"Asperoth Prime": "阿斯佩洛斯主星",
"Bellatrix": "参宿五",
"Botein": "天阴四",
"Osupsam": "欧苏普森",
"Brink-2": "布林克2",
"Bunda Secundus": "天垒城一次星",
"Canopus": "老人",
"Caph": "王良一",
"Castor": "北河二",
"Mort": "莫特",
"Charbal-VII": "查巴尔VII",
"Charon Prime": "卡戎主星",
"Choepessa IV": "科埃佩萨IV",
"Claorell": "可洛尔",
"Clasa": "克拉萨",
"Demiurg": "戴米尔基",
"Deneb Secundus": "天津四次星",
"Electra Bay": "昂宿一湾",
"Enuliale": "安努力亚",
"Epsilon Phoencis VI": "艾普斯林芬赛斯VI",
"Gacrux": "十字架一",
"Gar Haren": "轧尔哈伦",
"Gatria": "盖尔崔亚",
"Gemma": "贯索四",
"Grand Errant": "大艾伦特",
"Hadr": "马腹一",
"Haka": "哈卡",
"Haldus": "海德斯",
"Halies Port": "海利斯港",
"Herthon Secundus": "赫尔松次主星",
"Hesoe Prime": "海索主星",
"Heze Bay": "角宿二湾",
"Hort": "霍尔特",
"Hydrobius": "海德罗毕亚斯",
"Karlia": "卡利亚",
"Keid": "九州殊口增七",
"Khandark": "勘达尔克",
"Klaka 5": "克拉卡5",
"Kneth Port": "克奈斯港",
"Kraz": "轸宿四",
"Kuma": "天棓二",
"Lastofe": "赖斯斗夫",
"Leng Scundus": "蓝恩次星",
"Meissa": "觜宿一",
"Mekbuda": "井宿七",
"Merak": "北斗二",
"Merga IV": "玄戈增二IV",
"Minchir": "敏切尔",
"Mintoria": "敏托瑞亚",
"Morida 9": "摩帝亚9",
"Nabatea Secundus": "那贝塔次星",
"Navi VII": "阁道二",
"Overgoe Prime": "欧维果主星",
"Pandion-XXIV": "帕狄恩XXIV",
"Partion": "帕尔晨",
"Peacock": "孔雀十一",
"Phact Bay": "丈人一湾",
"Pherkad Secundus": "北极一次星",
"Polaris Prime": "北极星主星",
"Pollux 31": "北河三31",
"Prasa": "普拉萨",
"Propus": "五诸侯三",
"Ras Algethi": "帝坐",
"RD-4": "RD4",
"Rogue 5": "罗格5",
"Rirga Bay": "里尔加湾",
"Seasse": "西斯",
"Senge 23": "新戈23",
"Setia": "赛提亚",
"Shete": "赛特",
"Siemnot": "席姆纳特",
"Sirius": "天狼星",
"Skat bay": "斯卡特湾",
"Spherion": "斯飞利昂",
"Stor Tha Prime": "斯特萨主星",
"Stout": "斯图尔特",
"Termadon": "特尔玛登",
"Varylia 5": "瓦瑞拉亚",
"Wasat": "天樽二",
"Vega Bay": "织女一湾",
"Wezen": "弧矢一",
"Vindemitarix Prime": "文德米塔里克斯主星",
"X-45": "X45",
"Yed Prior": "天市右垣九",
"Zefia": "塞飞亚",
"Zosma": "太微右垣五",
"Zzaniah Prime": "藏尼亚主星",
"Skitter": "斯基特",
"Euphoria III": "欧福利亚III",
"Diaspora X": "大流散X",
"Gemstone Bluffs": "宝石崖",
"Zagon Prime": "扎贡主星",
"Omicron": "奥密克戎",
"Cyberstan": "生化斯坦",
"OSHAUNE": "欧绍恩",
"MARTALE": "玛尔特",
"HELLMIRE": "海尔迈尔",
"MATAR BAY": "玛塔",
"PENTA": "彭塔",
"ESTANU": "伊斯塔努",
"CHOOHE": "丘伊",
"CHORT BAY": "雀特湾",
"FORI PRIME": "佛里主星",
"SUPER EARTH": "超级地球",
"MARFARK": "玛尔法克",
"CRIMSICA": "克里姆西卡",
"MENKENT": "库楼三",
"LESATH": "尾宿八",
"VERNEN WELLS": "佛农井",
"NIVEL 43": "尼维尔43",
"DURGEN": "德尔根",
"TIBIT": "提比特",
"DRAUPNIR": "德罗普尼尔",
"MALEVELON CREEK": "麦拉芬蒙河",
"MAIA": "昂宿四",
"FENRIR III": "芬里尔III",
"ERRATA PRIME": "艾拉特主星",
"TROOST": "特鲁斯特",
"USTOTU": "伍斯特图",
"TURING": "图灵",
"ANGEL'S VENTURE": "天使投资",
"INGMAR": "英格玛",
"TIEN KWAN": "天关",
"UBANEA": "乌巴尼亚",
"VANDALON IV": "万达隆IV",
"MERIDIA": "默里迪亚",
"VELD": "维尔德",
"MANTES": "蒙特斯",
"KLEN DAHTH II": "克伦达斯II",
"PATHFINDER V": "开拓者V",
"WIDOW'S HARBOR": "寡妇港",
"NEW HAVEN": "纽黑文",
"PILEN V": "皮伦V",
"HYDROFALL PRIME": "水瀑主星",
"ZEA RUGOSIA": "泽亚鲁戈西亚",
"DARROWSPORT": "达罗斯波特",
"FORNSKOGUR II": "福恩斯科古尔",
"MIDASBURG": "弥达斯堡",
"CERBERUS IIIC": "刻耳帕洛斯IIIc",
"PROSPERITY FALLS": "繁荣瀑布",
"OKUL VI": "欧库VI",
"MARTYR'S BAY": "烈士湾",
"FREEDOM PEAK": "弗里敦峰",
"FORT UNION": "联合堡",
"KELVINOR": "开尔文奥尔",
"WRAITH": "幽灵",
"IGLA": "伊格勒",
"NEW KIRUNA": "新基鲁纳",
"FORT JUSTICE": "正义堡",
"ZEGEMA PARADISE": "泽格马乐土",
"PROVIDENCE": "普罗维登斯",
"PRIMORDIA": "普莱默迪亚",
"SULFURA": "萨尔弗拉",
"NUBLARIA I": "努布拉里亚I",
"KRAKATWO": "克拉克图",
"VOLTERRA": "沃尔泰拉",
"CRUCIBLE": "熔炉",
"VEIL": "帷幕",
"MARRE IV": "马尔IV",
"FORT SANCTUARY": "庇护堡",
"SEYSHEL BEACH": "塞舌尔海滩",
"EFFLUVIA": "艾芙鲁维亚",
"SOLGHAST": "索尔加斯特",
"DILVUIA": "迪卢维亚",
"VIRIDIA PRIME": "维尔伊迪主星",
"OBARI": "欧巴里",
"MYRADESH": "米拉戴什",
"ATRAMA": "阿特拉玛",
"EMERIA": "埃梅里亚",
"BARABOS": "巴勒博斯",
"FENMIRE": "范迈尔",
"MASTIA": "玛斯蒂亚",
"SHALLUS": "沙勒斯",
"KRAKABOS": "克拉克博斯",
"IRIDICA": "艾丽迪卡",
"AZTERRA": "艾孜泰拉",
"AZUR SECUNDUS": "艾热尔次星",
"IVIS": "艾维斯",
"SLIF": "斯利夫",
"CARAMOOR": "开勒莫尔",
"KHARST": "喀斯特",
"EUKORIA": "欧科里亚",
"MYRIUM": "梅里翁",
"KERTH SECUNDUS": "克斯次星",
"PARSH": "帕尔什",
"REAF": "利夫",
"IRULTA": "艾鲁尔塔",
"EMORATH": "艾莫拉斯",
"ILDUNA PRIME": "伊尔都纳主星",
"MAW": "深渊",
"BOREA": "博瑞亚",
"CURIA": "居里亚",
"TARSH": "塔尔什",
"SHELT": "谢尔特",
"IMBER": "因博尔",
"BLISTICA": "布里斯提卡",
"RATCH": "拉奇",
"JULHEIM": "尤尔海姆",
"VALGAARD": "瓦尔加德",
"ARKTURUS": "阿克图勒斯",
"ESKER": "艾斯克尔",
"TERREK": "泰雷克",
"CIRRUS": "希勒斯",
"HEETH": "希斯",
"ALTA V": "奥尔塔V",
"URSICA XI": "厄西卡XI",
"INARI": "伊纳里",
"SKAASH": "斯卡什",
"MORADESH": "莫拉戴什",
"RASP": "拉斯普",
"BASHYR": "巴希尔",
"REGNUS": "雷格努斯",
"MOG": "莫格",
"VALMOX": "瓦尔莫克斯",
"IRO": "伊罗",
"GRAFMERE": "格拉夫米尔",
"NEW STOCKHOLM": "新斯德哥尔摩",
"OASIS": "绿洲",
"GENESIS PRIME": "创世主星",
"OUTPOST 32": "32号哨站",
"CALYPSO": "卡利普索",
"ELYSIAN MEADOWS": "埃律西昂草原",
"ALDERIDGE COVE": "阿尔德里奇湾",
"TRANDOR": "特兰道尔",
"EAST IRIDIUM TRADING BAY": "东铱贸易湾",
"LIBERTY RIDGE": "解放岭",
"BALDRICK PRIME": "巴尔德里克主星",
"THE WEIR": "维尔",
"KUPER": "库珀",
"OSLO STATION": "奥斯陆站",
"PÖPLI IX": "珀普利IX",
"GUNVALD": "古恩瓦尔德",
"DOLPH": "多尔夫",
"BEKVAM III": "贝克温III",
"DUMA TYR": "杜马提尔",
"AERIS PASS": "亚萨关隘",
"AURORA BAY": "极光湾",
"GAELLIVARE": "耶利瓦勒",
"VOG-SOJOTH": "佛戈索约斯",
"KIRRIK": "基里克",
"MORTAX PRIME": "摩尔塔克斯主星",
"WILFORD STATION": "威尔福德站",
"PIONEER II": "先驱II",
"ERSON SANDS": "厄尔森桑兹",
"SOCORRO III": "索科罗III",
"BORE ROCK": "博尔岩",
"DARIUS II": "大流士II",
"ACAMAR IV": "天园六IV",
"ACHERNAR SECUNDUS": "水委一次星",
"ACHIRD III": "王良三III",
"ACRAB XI": "房宿四XI",
"ACRUX IX": "十字架二IX",
"ACUBENS PRIME": "柳宿增三主星",
"ADHARA": "弧矢七",
"AFOYAY BAY": "艾福亚湾",
"AIN-5": "毕宿—5",
"ALAIRT III": "艾列尔特III",
"ALAMAK VII": "天大将军——VII",
"ALARAPH": "右执法",
"ALATHFAR XI": "织女增三XI",
"ANDAR": "安达尔",
"ASPEROTH PRIME": "阿斯佩洛斯主星",
"BELLATRIX": "参宿五",
"BOTEIN": "天阴四",
"OSUPSAM": "欧苏普森",
"BRINK-2": "布林克2",
"BUNDA SECUNDUS": "天垒城一次星",
"CANOPUS": "老人",
"CAPH": "王良一",
"CASTOR": "北河二",
"MORT": "莫特",
"CHARBAL-VII": "查巴尔VII",
"CHARON PRIME": "卡戎主星",
"CHOEPESSA IV": "科埃佩萨IV",
"CLAORELL": "可洛尔",
"CLASA": "克拉萨",
"DEMIURG": "戴米尔基",
"DENEB SECUNDUS": "天津四次星",
"ELECTRA BAY": "昂宿一湾",
"ENULIALE": "安努力亚",
"EPSILON PHOENCIS VI": "艾普斯林芬赛斯VI",
"GACRUX": "十字架一",
"GAR HAREN": "轧尔哈伦",
"GATRIA": "盖尔崔亚",
"GEMMA": "贯索四",
"GRAND ERRANT": "大艾伦特",
"HADR": "马腹一",
"HAKA": "哈卡",
"HALDUS": "海德斯",
"HALIES PORT": "海利斯港",
"HERTHON SECUNDUS": "赫尔松次主星",
"HESOE PRIME": "海索主星",
"HEZE BAY": "角宿二湾",
"HORT": "霍尔特",
"HYDROBIUS": "海德罗毕亚斯",
"KARLIA": "卡利亚",
"KEID": "九州殊口增七",
"KHANDARK": "勘达尔克",
"KLAKA 5": "克拉卡5",
"KNETH PORT": "克奈斯港",
"KRAZ": "轸宿四",
"KUMA": "天棓二",
"LASTOFE": "赖斯斗夫",
"LENG SCUNDUS": "蓝恩次星",
"MEISSA": "觜宿一",
"MEKBUDA": "井宿七",
"MERAK": "北斗二",
"MERGA IV": "玄戈增二IV",
"MINCHIR": "敏切尔",
"MINTORIA": "敏托瑞亚",
"MORIDA 9": "摩帝亚9",
"NABATEA SECUNDUS": "那贝塔次星",
"NAVI VII": "阁道二",
"OVERGOE PRIME": "欧维果主星",
"PANDION-XXIV": "帕狄恩XXIV",
"PARTION": "帕尔晨",
"PEACOCK": "孔雀十一",
"PHACT BAY": "丈人一湾",
"PHERKAD SECUNDUS": "北极一次星",
"POLARIS PRIME": "北极星主星",
"POLLUX 31": "北河三31",
"PRASA": "普拉萨",
"PROPUS": "五诸侯三",
"RAS ALGETHI": "帝坐",
"ROGUE 5": "罗格5",
"RIRGA BAY": "里尔加湾",
"SEASSE": "西斯",
"SENGE 23": "新戈23",
"SETIA": "赛提亚",
"SHETE": "赛特",
"SIEMNOT": "席姆纳特",
"SIRIUS": "天狼星",
"SKAT BAY": "斯卡特湾",
"SPHERION": "斯飞利昂",
"STOR THA PRIME": "斯特萨主星",
"STOUT": "斯图尔特",
"TERMADON": "特尔玛登",
"VARYLIA 5": "瓦瑞拉亚",
"WASAT": "天樽二",
"VEGA BAY": "织女一湾",
"WEZEN": "弧矢一",
"VINDEMITARIX PRIME": "文德米塔里克斯主星",
"YED PRIOR": "天市右垣九",
"ZEFIA": "塞飞亚",
"ZOSMA": "太微右垣五",
"ZZANIAH PRIME": "藏尼亚主星",
"SKITTER": "斯基特",
"EUPHORIA III": "欧福利亚III",
"DIASPORA X": "大流散X",
"GEMSTONE BLUFFS": "宝石崖",
"ZAGON PRIME": "扎贡主星",
"OMICRON": "奥密克戎",
"CYBERSTAN": "生化斯坦"
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

@@ -0,0 +1,168 @@
import asyncio
import io
import json
import os
import re
from datetime import datetime
from typing import Optional, Union
import base64
from PIL import Image
from playwright.async_api import async_playwright
from nonebot.adapters.onebot.v11 import MessageEvent, MessageSegment
from nonebot import logger
basic_path = os.path.dirname(__file__)
save_path = os.path.join(basic_path, "temp")
headers = {
"User-Agent": "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.6) ",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "zh-cn"
}
def gen_ms_img(image: Union[bytes, Image.Image]) -> MessageSegment:
if isinstance(image, bytes):
return MessageSegment.image(
pic2b64(Image.open(io.BytesIO(image)))
)
else:
return MessageSegment.image(
pic2b64(image)
)
def get_present_time() -> int:
return int(datetime.timestamp(datetime.now()))
async def screen_shot(url: str, time_present: int) -> Optional[str or bool]:
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
try:
# 访问页面
await page.goto(url)
# 等待页面加载完成
await page.wait_for_load_state('domcontentloaded')
await page.wait_for_load_state('networkidle')
# 1. 获取卡片数量
card_selector = "div.flex.cursor-pointer[style*='width: 320px;']"
# 等待至少一个卡片元素出现
await page.wait_for_selector(card_selector, state='visible')
# 获取卡片数量
card_count = await page.eval_on_selector_all(card_selector, "els => els.length")
logger.info(f"获取到的星球卡片数量:{card_count}")
# 2. 单个卡片高度(固定为 270)
card_height = 270
extra_padding = 100 # 防止 margin、padding、gap
# 3. 计算所需 viewport 高度
if card_count == 0 or card_count <= 15:
logger.warning("卡片元素数量未超过设定值,使用默认视口高度。")
required_height = 1080 # 默认高度
else:
required_height = 1080 + (card_count - 15) / 5 * card_height + extra_padding
viewport_width = 1920 # 固定宽度
await page.set_viewport_size({"width": viewport_width, "height": required_height})
# 记录时间
time_start = get_present_time()
# 4. 加载替换文本的脚本
with open(f'{basic_path}/data/plantes_mix.json', 'r', encoding='utf-8') as file:
replacements = json.load(file)
# 构建替换脚本
replacement_script = ""
for keyword, replacement in replacements.items():
escaped_keyword = json.dumps(keyword)
escaped_replacement = json.dumps(replacement)
replacement_script += f"""
document.body.outerHTML = document.body.outerHTML.replace(new RegExp({escaped_keyword}, 'g'), {escaped_replacement});
"""
# 执行替换脚本
await page.evaluate(replacement_script)
# 结束时间
time_end = get_present_time()
duration = time_end - time_start
logger.info(f"截图文本替换耗时:{duration}s")
# 等待页面更新
await asyncio.sleep(1)
# 保存截图
logger.info("正在保存图片...")
img_path = os.path.join(save_path, f'{time_present}.png')
await page.screenshot(
path=img_path,
full_page=True
)
# 压缩图片
logger.info("正在压缩图片...")
img_convert = Image.open(img_path)
img_convert.save(img_path, quality=80)
logger.info("图片保存成功!")
except Exception as e:
logger.error(f"访问网站异常:{type(e)} `{e}`")
return f"访问网站异常:{type(e)} `{e}`"
finally:
await browser.close()
return "success"
async def screen_shot_2(url: str, time_present: int) -> Optional[str or bool]:
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
try:
# 设置视口大小
await page.set_viewport_size({"width": 1920, "height": 1080})
await page.goto(url)
await page.wait_for_load_state('networkidle')
with open(f'{basic_path}/data/plantes_mix.json', 'r', encoding='utf-8') as file:
replacements = json.load(file)
# 遍历字典,构建替换脚本
replacement_script = ""
for keyword, replacement in replacements.items():
escaped_keyword = json.dumps(keyword)
escaped_replacement = json.dumps(replacement)
replacement_script += f"""
document.body.outerHTML = document.body.outerHTML.replace(new RegExp({escaped_keyword}, 'g'), {escaped_replacement});
"""
# 在页面上执行替换脚本
await page.evaluate(replacement_script)
except Exception as e:
return f"访问网站异常{type(e)}`{e}`"
await asyncio.sleep(1)
logger.info("正在保存图片...")
img_path = os.path.join(save_path, f'{time_present}.png')
await page.screenshot(
path=img_path,
full_page=True
)
logger.info("正在压缩图片...")
img_convert = Image.open(img_path)
img_convert.save(img_path, quality=80)
logger.info("图片保存成功!")
await browser.close()
return "success"
def pic2b64(pic: Image) -> str:
buf = io.BytesIO()
pic.save(buf, format='PNG')
base64_str = base64.b64encode(buf.getvalue()).decode()
return 'base64://' + base64_str