参考资料 & 测试
- 前端渲染及 SSR:card.js「GitHub Repo」「Demo」「卡图」
- 鼠标悬浮提示框参考:Steam Info「出处:其乐论坛」「Greasy Fork」「源码」
- Hugo:自定义 shortcode「Shortcode 文档」「基本语法」「函数」
一个小 bug
这是一个 bug:`<div class="ygo-card" />` **首次**出现的时候 _前面的文本_ 会被视为一个段落 `<p/>` 进而导致自动换行,考虑使用双层 `<span/>` 嵌套尝试修复{{< ygo-card 禁忌的一滴 24299458 spell sg >}}测试文本测试文本测试文本测试文本{{< ygo-card name="青眼白龙" id="89631139" type="light" >}}测试文本测试文本测试文本测试文本测试文本测试文本测试文本{{< ygo-card name="红色重启" id="23002292" type="trap" icon="fj" >}}测试文本测试文本测试文本测试文本测试文本{{< ygo-card >}}测试文本测试文本测试文本测试测试文本
这是一个 bug:<div class="ygo-card" />
首次出现的时候 前面的文本 会被视为一个段落 <p/>
进而导致自动换行,考虑使用双层 <span/>
嵌套尝试修复
需求
考虑做成一个前端网站。这里临时用 JS 做可行性验证,到时候还是用 TS 写。
Todo List
- 卡组格式转换 ydk ygm 等,类似「YGO-Engine 的 ydk 和 ygm 转换」
- 从录像文件
.yrp
中提取卡组信息,类似「OURYGO 的」和「YGO-Engine 的」 - 展现卡图,类似「OURYGO 的」和「Koishi 的」
- 点击卡组中的单卡跳转卡查页面
-
不用 jq(我不想)实现鼠标浮(hover)在单卡上弹出悬浮对话框显示卡片详情 -
在线编辑卡组,类似 YGOPro 编辑卡组功能(或许可以用 godot 写成桌面端?) - 原来做 DLM 的现在做 MD 了(MDM):「Master Duel Meta - Deck Builder」
完美实现我想要的所有需求(从录像提取卡组除外,待实现) -
获取 MDM 的卡组,当然可以做爬虫,但有现成的可以抄,试着抄现成:- 逆向目标:拓王神 组卡器 2.2 - 对应 MD 1.02 里的
masterduelmeta导出卡组.exe
- pyinstxtractor 把
.exe
反编译成.pyc
- 由于每个
.pyc
文件都有 magic head,pyinstaller 生成 exe 的时候会把 pyc 的 magic 部分去掉,所以在反编译的时候需要自己补齐 - 通过
struct
文件获取前 4 个字节(Python 编译的版本),加上00 00 00 00
4 个字节(本来应该是时间戳,不重要)组成 magic head - 通过 WinHex 或者 hexed.it 等工具把 magic head 重新写入
.pyc
文件开头 - 发现 pyinstxtractor 生成
.pyc
的已经是还原了 magic head 后的版本了,我就是过期资料的受害者 - 在线反编译 pyc 或者 uncompyle6(不支持 Python 3.9 及以上,之前重装过电脑上只有 3.10,我还专门去装了个 3.8.6)把
.pyc
/.pyo
反编译成.py
源文件 - 失败,原因不明。到目前为止沉没的时间成本已经够多了,该及时止损了,打住打住
- 逆向目标:拓王神 组卡器 2.2 - 对应 MD 1.02 里的
- 自己写爬虫
- 本来应该用异步请求库 aiohttp,但没有大规模用途,临时用 requests 就够了
- DLM 的反爬做得可以啊,赞叹(你以前不是爬过吗
什么记忆只有 7 秒的弱智金鱼),静态网页只有<a class="image-wrapper svelte-152ds40 card-image-loading" /a>
的占位符,具体内容后续动态加载,进一步使用 Selenium + PhantomJS 模拟浏览器加载 JS - 获得的 HTML 用 Beautiful Soup 4(以及 lxml 提高效率)解析
- 还原卡名,
from urllib.parse import unquote
解码 url 编码 - 卡片数据以前我是去 YGOPro 偷的根目录下的
card.cdb
(sqlite3),现在正好手上一堆 MD 相关工具,基本人手一个转换好的cards.json
,直接用现成的了 - 妈的优化做多了有点入脑了,老是满脑子效率,魔怔了属于是。随便写个脚本难道还能有百万吞吐?真的怪。直接
json.loads(file.read())
读成字典暴力遍历就完事了 - 搞定,输入 MDM 网址,输出 ydk 格式卡组代码
- 顺手把批量转换卡名写了,支持将整个卡组切换为中文名、日文名、英文名
可部分选中,也提供一键复制按钮用脚本写的不考虑人机交互 - 爽到,从现在开始可以一行命令把
masterduelmeta.com
的卡组抄到博客来了
最后还是重复造轮子了?
没有哦,masterduelmeta导出卡组.exe
这个工具只能导出卡组,对其他格式毫无办法
而我有导出任何卡组的需求,比如《「NR 杯」卡组构筑》里用到的 NR 杯禁限卡表
ydk 卡组代码
众所周知,广为流传的 .ydk
格式简单易懂:
#main
后面 - 主卡组#extra
后面 - 额外卡组!side
后面 - 副卡组
每行一个卡密,每个卡密代表一张卡。
#备注 随便写什么
#main
71039903
71039903
71039903
45467446
89631139
89631139
89631139
38517737
22804410
55410871
24094653
21082832
#extra
2129638
56532353
59822133
59822133
40908371
40908371
!side
20654247
43228023
感谢 Hugo 强大的 shortcode 功能 支持高度客制化玩法,允许我轻松实现下面的呈现效果。
卡查用的 百鸽;卡图来自momobako.com
这个域名的 CDN(由知乎用户 Nanahira 提供)。
2022.5 更新:
- 重构:解析方式使用 Markdown 代码块代替之前的 Hugo shortcode
(混合 Go 的 HTML → JavaScript)- 样式:改进边框,利用 CSS 实现 3D 悬浮卡片特效
- 样式:改进排版,换用 SVG 强制规定尺寸和位置,支持无极缩放 & 动态自适应容器大小
- 优化:现在真的有检测图片,如果不存在则自动回退(fallback)的机制了(红色占位图)
- 优化:辅助排版时的占位图现在使用的是本地图片了(蓝色占位图),之前是第三方接口生成的
- 优化:占位图没有点击跳转的超链接,鼠标指针 hover 也不会变
- 优化:卡组信息不再解析所谓的「评论」,卡组就是卡组,就你话多,要评自己另外找地方 BB
- TODO:生成按钮,支持一键复制
ydk
代码- TODO:自动生成外链,允许新窗口打开卡组(类似这样)
处理 ydk
这个格式真的蛮好,
|
|
ygm 格式 卡组分享码
解析成功之后像「ygo-sem.cn 的 ydk / ygm 分享码互相转换」这样的工具做起来也很简单了。
|
|
所谓 ygm 就是早年间安卓端 YGOMobile 的卡组分享码格式,现在已经被淘汰了。
(最新版的 YGOMobile 用的是下面提到的 DA 协议。)
而 ydk 被包括 YGOPro 在内的各种桌面端广泛支持和使用,并允许以.ydk
格式的文件保存。
DA 协议分析
闭门造车不可取,有现成的可用没必要标新立异非要自己重新设计。
参考现有的《YGO 决斗助手协议》(简称 DA 协议)的设计完成长度压缩算法。这兄弟文档写得有点乱,费了点劲才看明白。
base64 编码「文本」是 3 字节 → 4 字节,平白多出 33% 的冗余,显然跟压缩沾不上边。
但这里记录的是「纯数值」,用 base64 旨在压缩长度——把一长串卡组信息压成一行字符。
不要挑我字眼。
单卡
每一种类不同的卡,为一个「29 位的二进制数」,具体组成为「
|
|
卡组
按照 主卡组
+ 额外卡组
+ 副卡组
的顺序把单卡依次拼接起来即可。
还要注意记录各个卡组的单卡种类数量,并将数量也转换为固定长度的二进制数放在开头。
主卡组种类数量 | 额外卡组种类数量 | 副卡组种类数量 | 主卡组构成 | 额外卡组构成 | 副卡组构成 |
---|---|---|---|---|---|
8 位 | 4 位 | 4 位 | 29 位 × n 种 | 29 位 × m 种 | 29 位 × p 种 |
|
|
得到下面生成的链接:
http://deck.ourygo.top/ydk/show.html?ygotype=deck&v=1&d=B0Lh39z6rXHNuq9TRqS7vpSt-90tNgLdKDZaCCB-5lr07AzkNA1k4Gymk7KKdUnNu4A
打开链接 验证效果,完美。