From 79cd63fb8f735c071533970b3fe668c690702ebd Mon Sep 17 00:00:00 2001
From: SlyAimer <2289782085@qq.com>
Date: Sun, 16 Feb 2025 14:36:24 +0800
Subject: [PATCH] =?UTF-8?q?feat(plugins):=20=E6=96=B0=E5=A2=9E=20yuc=5Fwik?=
=?UTF-8?q?i=20=E6=8F=92=E4=BB=B6=E5=8F=8A=E7=9B=B8=E5=85=B3=E9=85=8D?=
=?UTF-8?q?=E7=BD=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 新增 yuc_wiki 插件,支持查询本季新番和动漫信息
- 添加 yuc_wiki 图片存储路径配置
- 更新 .gitignore 忽略 yuc_wiki 图片目录
- 更新 requirements.txt 添加 cssutils 依赖
- 更新 check.py 菜单项,添加 yuc_wiki 相关命令
---
.gitignore | 1 +
requirements.txt | 1 +
src/clover_yuc_wiki/yuc_wiki.py | 120 ++++++++++++++++++++++++++++++++
src/configs/path_config.py | 3 +
src/plugins/check.py | 2 +-
src/plugins/yuc_wiki.py | 15 ++++
6 files changed, 141 insertions(+), 1 deletion(-)
create mode 100644 src/clover_yuc_wiki/yuc_wiki.py
create mode 100644 src/plugins/yuc_wiki.py
diff --git a/.gitignore b/.gitignore
index a45a254..06b38dd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,3 +23,4 @@ bili.cookie
/src/resources/image/report/*
/src/resources/image/lightnovel/*
/wenku8.cookie
+/src/resources/image/yuc_wiki/*
diff --git a/requirements.txt b/requirements.txt
index 574768e..205fd1c 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -25,6 +25,7 @@ playwright
nonebot-plugin-htmlrender
tenacity
paramiko
+cssutils
requests
pillow
diff --git a/src/clover_yuc_wiki/yuc_wiki.py b/src/clover_yuc_wiki/yuc_wiki.py
new file mode 100644
index 0000000..08666a7
--- /dev/null
+++ b/src/clover_yuc_wiki/yuc_wiki.py
@@ -0,0 +1,120 @@
+import os
+from pathlib import Path
+import requests
+from os import getcwd
+from bs4 import BeautifulSoup
+from datetime import datetime
+from nonebot_plugin_htmlrender import template_to_pic
+from src.configs.path_config import yuc_wiki_path
+
+base_url = "https://yuc.wiki/"
+new = "https://yuc.wiki/new"
+
+async def get_yuc_wiki(keyword):
+ """
+ 获取当季动漫
+ """
+ try:
+ if keyword == '本季新番':
+ template_name = await generate_season_url()
+ response = requests.get(base_url + f'{template_name}', timeout=10)
+ else:
+ template_name = 'forecast_anime'
+ response = requests.get(new, timeout=10)
+
+ soup = await dispose_html(response)
+ with open(yuc_wiki_path+f'{template_name}.html', 'w', encoding='utf-8') as f:
+ f.write(str(soup))
+ await get_yuc_wiki_image(template_name,568,1885)
+ except (Exception, IOError) as e:
+ print(f"Error occurred: {e}")
+
+ return yuc_wiki_path+f'{template_name}.jpeg'
+
+async def generate_season_url():
+ """
+ 获取当前季度
+ :return:
+ """
+ now = datetime.now()
+ quarter_month = ((now.month - 1) // 3) * 3 + 1
+ return f"{now.year}{quarter_month:02d}"
+
+async def dispose_html(response):
+ """
+ 处理html
+ :param response:
+ :return:
+ """
+ response.raise_for_status()
+ soup = BeautifulSoup(response.text, 'html.parser')
+ # 删除第一个 table 标签
+ first_table = soup.select_one('table')
+ if first_table:
+ first_table.decompose()
+ # 批量处理需要删除的标签
+ for tag in soup.select('header, aside'):
+ tag.decompose()
+
+ # 查找第二个
标签
+ hr_tags = soup.find_all('hr')
+ if len(hr_tags) >= 2:
+ second_hr = hr_tags[1]
+ # 删除第二个
标签之后的所有内容
+ next_element = second_hr.next_sibling
+ while next_element:
+ next_sibling = next_element.next_sibling
+ next_element.extract()
+ next_element = next_sibling
+
+ # 统一处理资源路径
+ for tag in soup.find_all(['a', 'link', 'img', 'script', 'source']):
+ # 处理图片懒加载
+ if tag.name == 'img' and tag.get('data-src'):
+ tag['src'] = tag['data-src']
+ del tag['data-src']
+ # 统一修正路径
+ attr = 'href' if tag.name in ['a', 'link'] else 'src'
+ if tag.has_attr(attr):
+ path = tag[attr].lstrip('/\\')
+ if not path.startswith(('http://', 'https://')):
+ tag[attr] = f"{base_url}{path}"
+ if path.startswith('http://'):
+ tag[attr] = path.replace('http://', 'https://', 1)
+ return soup
+
+async def get_yuc_wiki_image(template_name,width,height):
+
+ file = Path() / yuc_wiki_path / f"{template_name}.jpeg"
+ if os.path.exists(file):
+ with file.open("rb") as image_file:
+ return image_file.read()
+
+ image_bytes = await template_to_pic(
+ template_path=yuc_wiki_path,
+ template_name=f'{template_name}.html',
+ templates={"data": None},
+ quality=90,
+ type="jpeg",
+ pages={
+ "viewport": {"width": width, "height": height},
+ "base_url": f"file://{getcwd()}",
+ },
+ wait=2,
+ )
+ await save_img(image_bytes,template_name)
+
+async def save_img(data: bytes,template_name : str):
+
+ """
+ 保存yuc_wiki图片
+ :param template_name:
+ :param data:
+ :return:
+ """
+ file_path = yuc_wiki_path + f"{template_name}.jpeg"
+ with open(file_path, "wb") as file:
+ file.write(data)
+ print("保存图片完成")
+
+
diff --git a/src/configs/path_config.py b/src/configs/path_config.py
index 2eb4898..76d52d3 100644
--- a/src/configs/path_config.py
+++ b/src/configs/path_config.py
@@ -28,6 +28,9 @@ os.makedirs(daily_news_path, exist_ok=True)
# 轻小说
light_novel_path = path + '/image/lightnovel/'
os.makedirs(light_novel_path, exist_ok=True)
+#yuc_wiki 动漫wiki
+yuc_wiki_path = path + '/image/yuc_wiki/'
+os.makedirs(yuc_wiki_path, exist_ok=True)
# 字体路径
font_path = path + '/font/'
os.makedirs(font_path, exist_ok=True)
diff --git a/src/plugins/check.py b/src/plugins/check.py
index fb484de..b5f0af4 100644
--- a/src/plugins/check.py
+++ b/src/plugins/check.py
@@ -10,7 +10,7 @@ from src.clover_sqlite.models.user import UserList
menu = ['/重启','/今日运势','/今日塔罗','/图','/日报','/点歌','/摸摸头','/群老婆','/今日老婆', "/开启ai","/关闭ai","/角色列表","/添加人设", "/更新人设", "/删除人设", "/切换人设", "/管理员注册",
'/待办', '/test','/天气','我喜欢你', "❤", "/待办查询", "/新建待办", "/删除待办" ,"/cf","/B站搜索", "/BV搜索", "/喜报", "/悲报", "/luxun","/鲁迅说",
- "/奶龙", "/repo", "/info", "/menu", "/轻小说"]
+ "/奶龙", "/repo", "/info", "/menu", "/轻小说",'/本季新番','/新番观察']
send_menu = ["/开启ai","/关闭ai","/角色列表","/添加人设", "/更新人设", "/删除人设", "/切换人设", "/管理员注册", '/待办', '/test', '我喜欢你', "❤", "/menu"]
diff --git a/src/plugins/yuc_wiki.py b/src/plugins/yuc_wiki.py
new file mode 100644
index 0000000..d9b5d27
--- /dev/null
+++ b/src/plugins/yuc_wiki.py
@@ -0,0 +1,15 @@
+from pathlib import Path
+from nonebot.rule import to_me
+from nonebot.plugin import on_command
+from nonebot.adapters.qq import MessageSegment,MessageEvent
+from src.clover_yuc_wiki.yuc_wiki import get_yuc_wiki
+
+
+
+yuc_wiki = on_command("本季新番",aliases={'新番观察'} ,rule=to_me(), priority=10, block=True)
+@yuc_wiki.handle()
+async def handle_function(message: MessageEvent):
+ keyword = message.get_plaintext().replace("/", "").strip(" ")
+ yuc_wiki_image = await get_yuc_wiki(keyword)
+ await yuc_wiki.send("请稍等。。。")
+ await yuc_wiki.finish(MessageSegment.file_image(Path(yuc_wiki_image)))