群搜图小助手
吐槽
已经不是热点了~
就在今天(2022年5月17日),一则合并消息传遍了整个 QQ 群
转发的合并消息(有部分删减)
L
LIAN-小明
隔壁群的机器人已经可以识别本子了
L
LIAN-小明
好家伙 黄油也能识别
L
LIAN-小明
咱们群不行啊 叫群主也搞一个这种高科技的机器人才行
看起来,这个合并消息很大程度激发了大家对于 QQ 机器人的乐趣
所以,我决定现在在这里再新加一节教你如何制作搜涩图的机器人
0. 先做一个能用的机器人
假设你并没有看过该文档的其他章节, 那请先到目录, 跟着我们的教程看完「从零开始的异世界涩图机器人教程」的前三章。
1. 申请一个 saucenao 的 apikey
根据我们对这次事件的核心机器人 真寻bot 的解析, 我们可以知道,机器人的搜图功能事实上是通过调用 Saucenao 的 api 来实现的。 所以,让我们先注册一个 apikey
TIP
你可能很好奇为什么这里没有图
因为是特别篇章嘛,写的有点急,嘿嘿
- 打开 Saucenao,点击右下角的
Account
- 在
Register
中注册你的账号 - 注册登录成功后,点击个人页面左上角的
api
- 然后在那一大串英文中出现的
api key
就是我们需要的东西啦
2. 安装 saucenao-api
sh
pdm add saucenao-api
1
sh
poetry add saucenao-api
1
sh
pip install saucenao-api
1
3. 在插件文件夹里创建一个新的插件并且粘贴一下代码
python
from graia.ariadne.app import Ariadne
from graia.ariadne.event.message import GroupMessage
from graia.ariadne.message.chain import MessageChain
from graia.ariadne.message.element import *
from graia.ariadne.message.parser.twilight import Twilight, FullMatch, ElementMatch, ElementResult
from graia.ariadne.model import Group, Member
from graia.saya import Channel
from graia.saya.builtins.broadcast.schema import ListenerSchema
from saucenao_api import AIOSauceNao
from saucenao_api.errors import SauceNaoApiError
channel = Channel.current()
channel.name("Saucenao")
channel.description("以图搜图")
channel.author("I_love_study")
apikey = "xxx" # 请输你自己的,谢谢
@channel.use(
ListenerSchema(
listening_events=[GroupMessage],
inline_dispatchers=[
Twilight(
FullMatch("以图搜图"),
FullMatch("\n", optional=True),
"img" @ ElementMatch(Image, optional=True),
),
],
)
)
async def saucenao(app: Ariadne, group: Group, member: Member, img: ElementResult, source: Source):
await app.send_group_message(group, MessageChain("正在搜索,请稍后"), quote=source.id)
async with AIOSauceNao(apikey, numres=3) as snao:
try:
results = await snao.from_url(img.result.url)
except SauceNaoApiError as e:
await app.send_message(group, MessageChain("搜索失败desu"))
return
fwd_nodeList = []
for results in results.results:
if len(results.urls) == 0:
continue
urls = "\n".join(results.urls)
fwd_nodeList.append(
ForwardNode(
target=app.account,
senderName="爷",
time=datetime.now(),
message=MessageChain(
f"相似度:{results.similarity}%\n标题:{results.title}\n节点名:{results.index_name}\n链接:{urls}"
)))
if len(fwd_nodeList) == 0:
await app.send_message(group, MessageChain("未找到有价值的数据"), quote=source.id)
else:
await app.send_message(group, MessageChain(Forward(nodeList=fwd_nodeList)))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
python
from graia.ariadne.app import Ariadne
from graia.ariadne.message.element import *
from graia.ariadne.model import Group
from graia.saya import Channel
from arclet.alconna import Args, CommandMeta
from arclet.alconna.graia import Alconna, alcommand, ImgOrUrl, Match
from saucenao_api import AIOSauceNao
from saucenao_api.errors import SauceNaoApiError
channel = Channel.current()
channel.name("Saucenao")
channel.description("以图搜图")
channel.author("RF-Tar-Railt")
apikey = "xxx" # 请输你自己的,谢谢
search = Alconna(
".搜图",
Args["content", ImgOrUrl],
meta=CommandMeta(
"以图搜图,搜图结果会自动发送给你",
usage="你既可以传入图片, 也可以传入图片链接",
example=".搜图 [图片]"
)
)
@alcommand(search, private=False)
async def saucenao(app: Ariadne, group: Group, source: Source, content: Match[str]):
if not content.available:
return await app.send_group_message(group, MessageChain("啊嘞,你传入了个啥子东西"), quote=source.id)
await app.send_group_message(group, MessageChain("正在搜索,请稍后"), quote=source.id)
async with AIOSauceNao(apikey, numres=3) as snao:
try:
results = await snao.from_url(content.result)
except SauceNaoApiError as e:
await app.send_message(group, MessageChain("搜索失败desu"))
return
fwd_nodeList = []
for results in results.results:
if len(results.urls) == 0:
continue
urls = "\n".join(results.urls)
fwd_nodeList.append(
ForwardNode(
target=app.account,
senderName="爷",
time=datetime.now(),
message=MessageChain(
f"相似度:{results.similarity}%\n标题:{results.title}\n节点名:{results.index_name}\n链接:{urls}"
)))
if len(fwd_nodeList) == 0:
await app.send_message(group, MessageChain("未找到有价值的数据"), quote=source.id)
else:
await app.send_message(group, MessageChain(Forward(nodeList=fwd_nodeList)))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
这样,你的搜图机器人就做好力
转发的合并消息
爷
爷
以图搜图
EroEroBot
EroEroBot
群聊
爷: 相似度:96.87% ...
爷: 相似度:95.54% ...
爷: 相似度:87.62% ...
查看3条转发消息
4. 背后原理
假设你真的很想知道这些东西背后的原理,你可以直接参考以下章节