ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Cataclysm-DDA JSON 数据挖掘指南:keys.py 与 values.py 实战解析

Cataclysm-DDA JSON 数据挖掘指南:keys.py 与 values.py 实战解析 Cataclysm-DDA JSON 数据挖掘指南keys.py 与 values.py 实战解析【免费下载链接】Cataclysm-DDACataclysm - Dark Days Ahead. A turn-based survival game set in a post-apocalyptic world.项目地址: https://gitcode.com/GitHub_Trending/ca/Cataclysm-DDA本文面向 Cataclysm-DDACDDA的模组作者、内容维护者与数据研究者系统讲解仓库 tools/json_tools/ 目录下基于 Python 与 jq 编写的 JSON 分析工具链。你将掌握如何使用keys.py、values.py、lister.py等脚本对 data/json 中数以万计的游戏数据 blob 进行字段统计、取值枚举、条件过滤与嵌套对象下钻并理解其底层实现原理从而在日常模组开发、平衡性调参与数据审查中快速获得可复现的量化结论。工具链概览tools/json_tools 目录Cataclysm-DDA 的绝大多数游戏内容物品、怪物、配方、地形、魔法、变异等都以 JSON 格式存放于 data/json 目录。随着版本迭代该目录下已有数千个 JSON 文件、数万个数据对象blob。手工翻阅这些文件来回答有多少工具定义了longest_side、哪些护甲用皮革制作之类的问题是低效且易错的。为此仓库在 tools/json_tools/ 下提供了一批用Python 3和jq编写的命令行工具用于对这批 JSON 数据进行统计与筛选。核心工具及其职责如下脚本作用keys.py统计匹配对象中每个键字段出现的次数values.py统计某个键下各个取值出现的次数lister.py从 stdin 的 JSON 输入中提取去重、排序后的键/值列表pluck.py按条件匹配并输出完整 JSON 对象table.py将指定字段输出为 Markdown 或 CSV 表格util.py公共函数库数据导入、where 过滤、计数、格式化输出jq/一批 jq 脚本如count_json_entities.jq、enumerate_json_entities.jqPython 侧仅依赖标准库唯一的第三方依赖Pillow9.0.0见 requirements.txt且仅为generate_overmap_sprites.py生成地形图块所用与统计工具无关——因此统计类脚本在绝大多数 Python 3 环境下开箱即用。keys.py 与 values.py一对互补的统计脚本keys.py与values.py是这套工具链的核心用法高度相似keys.py统计每个键字段在整个匹配数据集中出现的次数。例如你可以用它了解有多少物品定义了weight或volume或者overmap_special类型最常使用哪些字段。values.py统计某个给定键下每个取值出现的次数。例如你想知道物品的volume或weight有哪些不同的取值或者想从一组匹配物品中查询全部id。两个脚本都支持通过-h查看命令行帮助。默认输出为 JSON 文本传入--human选项后则以更易读的列格式输出。命令行参数详解源码视角查看 keys.py 与 values.py 的参数定义两者共享以下选项参数含义默认值--fnmatch覆盖默认 glob 表达式用于挑选更小的文件集*.json-H, --human输出人类可读格式默认输出 JSON关闭-L, --list仅输出排序后的键/值列表JSON 数组配合--human时输出换行分隔的纯文本关闭where位置参数形如where_keywhere_val的过滤条件可写多个多个条件之间为AND关系无-k, --key仅 values.py指定要统计取值的键必填无实际运行中--fnmatch可配合例如--fnmatch*.json在data/json下按文件名挑选子集--list常与lister.py的管道用法配合见下文。从仓库根目录运行你可以在仓库根目录Cataclysm-DDA下使用相对路径直接运行前提是脚本具备执行权限或使用python3调用$ tools/json_tools/keys.py -h $ tools/json_tools/keys.py --human typeTOOL $ tools/json_tools/values.py --key material typeTOOL进入目录运行也可以先cd进tools/json_tools目录再执行效果完全一致$ cd tools/json_tools $ ./keys.py -h $ ./keys.py --human typeTOOL $ ./values.py --key material typeTOOL之所以两种方式都可用是因为数据目录路径是通过脚本自身位置推算的而非依赖当前工作目录。在 util.py 中可以看到SCRIPT_DIR os.path.abspath(os.path.dirname(__file__)) JSON_DIR os.path.normpath( os.path.join(SCRIPT_DIR, .., .., data, json))也就是说无论从哪个目录调用脚本它都会基于自身所在路径回溯两级定位到仓库的data/json目录。import_data函数util.py会递归遍历该目录下所有匹配*.json默认的文件将每个文件解析出的对象或对象列表汇集成一个大的数据列表返回。解析使用object_pairs_hookOrderedDict保留字段顺序文件无法解析或内容不是对象/对象列表时会被记入错误列表并在脚本入口处以 Error loading JSON data. 形式报错退出参见 keys.py。where 过滤机制灵活的键值匹配两个脚本的核心筛选能力来自位置参数where其格式为where_keywhere_val可叠加多个AND 语义且值部分会被当作正则表达式进行匹配。这一机制由 util.py 中的WhereAction一个 argparse action 回调实现命令行每个kv被拆分为键与值包装成where_test_factory返回的可调用谓词matches_all_wheresutil.py要求所有谓词同时为真才保留该对象。具体匹配规则见matches_where与match_primitive_valuesutil.py字符串值直接用re.match(where_value, item_value)做正则前缀匹配数字值先转为字符串再正则匹配如materialsteel匹配值为steel的条目布尔值转为小写字符串后匹配因此可用activetrue这样的写法列表值对列表内元素逐个匹配任一命中即通过字典值对其键名做匹配。例如values.py -k cost typebionic activetruevalues.py 自带示例可以统计所有active为true的生化改造的cost取值。正则匹配意味着materialkev也能命中kevlar为模糊查询提供了便利。实战示例一keys.py 统计 TOOL 类型的字段覆盖以keys.py统计有多少TOOL类型物品定义了各个键输出已省略长列表$ tools/json_tools/keys.py --human typeTOOL Count of keys (Data from 752 out of 25050 blobs) ------------- type : 752 name : 752 weight : 656 pocket_data : 143 looks_like : 101 techniques : 92 longest_side : 56 ...这段输出说明在当时的data/json中共解析出 25050 个 blob其中 752 个是TOOL类型所有工具都定义了type与name但只有 143 个定义了pocket_data、56 个定义了longest_side——这类覆盖率信息对判断某字段是否需要补全、某项数据是否规范非常有价值。实现层面key_counterutil.py对每个匹配对象遍历键跳过//开头的注释键并对对象值、对象列表值进行一级下钻生成parent.child形式的点号键其余类型按一次计数最后返回Counter统计结果与匹配对象数。--human模式下标题行里的(Data from 752 out of 25050 blobs)即来自key_counter返回的(stats, num_matches)元组。实战示例二values.py 统计 material 取值分布values.py打印TOOL类型物品中每个material取值的出现次数。MISSING列表示有多少工具在 JSON 中未定义material$ tools/json_tools/values.py --key material --human typeTOOL Count of values from field material (Data from 752 out of 25050 blobs) ------------- steel : 295 plastic : 245 MISSING : 105 aluminum : 73 wood : 70 glass : 35 ...这里的MISSING统计来自value_counterutil.py当匹配对象中不存在parent_key时计数器直接为MISSING加一。取值本身会递归收集字符串按原文计数数字被转为字符串计数字典取全部值、列表逐元素收集见item_value_counter与list_value_counterutil.py。组合多个过滤条件where支持叠加多个条件进一步收窄范围。例如统计weapon分类下TOOL类型物品的longest_side取值并保留未定义该项的数量$ tools/json_tools/values.py --key longest_side typeTOOL categoryweapon {50 cm: 10, 40 cm, 1, MISSING: 95, 20 cm: 2, 100 cm: 6, ...}注意这里没有加--human因此输出为紧凑 JSON 字典便于程序化处理。管道与 lister.py提取去重列表values.py的 JSON 输出可以继续通过管道交给lister.py得到去重且按字母排序的键列表。例如列出全部 JSON 数据中的type取值而不关心每种各有多少个$ tools/json_tools/values.py --key type | tools/json_tools/lister.py [AMMO, ARMOR, BATTERY, BIONIC_ITEM, BOOK, COMESTIBLE, ...]lister.pylister.py从 stdin 读取 JSON字典或列表均可把所有键收集进set去重后排序再输出 JSON 数组传入--human则按等宽多列输出纯文本。它要求数据必须通过管道或文件重定向输入——若在终端直接运行脚本会检测到输入不是管道FIFO也不是普通文件提示 Redirect data to stdin, please 并退出。这一设计使其天然适合与其他脚本串联。同理keys.py的--list模式也可单独输出排序键列表或与lister.py组合。点号嵌套键透视对象内部字段CDDA 的 JSON 中许多字段是嵌套对象或对象数组例如name常为包含复数形式的对象pocket_data则是对象列表。keys.py对这类结构会输出parent.child形式的点号键$ tools/json_tools/keys.py typeARMOR | tools/json_tools/lister.py { ..., pocket_data.max_contains_volume, pocket_data.max_item_length, pocket_data.pocket_type, ... }这些点号键可以直接作为values.py的-k/--key参数用于透视嵌套对象内部的值。例如查看ARMOR类型各pocket_data对象中的max_item_length取值分布$ tools/json_tools/values.py -k pocket_data.max_item_length typeARMOR { 25 cm: 1, 140 cm: 1, 16 cm: 1, 50 cm: 5, MISSING: 785, ... }源码对点号键的支持见value_counterutil.py恰好含一个.时拆分为parent_key与child_key不含.时仅按普通键处理含多个.时直接抛出参数错误Only one . allowed in search key。统计时若parent_key是对象列表则收集每个对象中child_key的值若是单个对象则取其中child_key的值否则按普通值处理。这解释了为什么monsters.conditions这类列表内对象字段也能被直接统计见下文用例表。完整用例速查表官方文档给出了一份实用的需求 → 命令对照表这里完整收录并补充说明统计某类对象的字段使用情况keys.py想要统计的字段命令行material类型的字段keys.py typematerialovermap_special类型的字段keys.py typeovermap_specialweapons分类的字段keys.py categoryweapons木制weapons的字段keys.py categoryweapons materialwood查询特定字段的取值分布values.py想要的信息命令行所有 JSON 数据中的全部type值values.py -k type所有 JSON 数据中的全部category值values.py -k categorymaterial含kevlar的物品 IDvalues.py -k id materialkevlar所有MAGAZINE类型的 IDvalues.py -k id typeMAGAZINE所有GUN物品的材料values.py -k material typeGUN所有TOOL物品的材料values.py -k material typeTOOL皮革ARMOR的encumbrancevalues.py -k encumbrance typeARMOR materialleather所有mutation类型的category值values.py -k category typemutationCOMESTIBLE物品的成瘾类型values.py -k addiction_type typeCOMESTIBLESPELL类型的合法目标values.py -k valid_targets typeSPELLmonstergroup类型中的怪物出现条件values.py -k monsters.conditions typemonstergroup这些命令均可在仓库根目录直接运行如tools/json_tools/values.py -k id typeMAGAZINE。由于materialkevlar等条件走正则匹配必要时可加^锚定如material^kevlar$实现精确匹配。注意where与键名大小写敏感CDDA 的type值习惯使用全大写枚举名如TOOL、GUN、ARMOR、MAGAZINE、COMESTIBLE、SPELL、mutation、monstergroup。延伸配套工具与 jq 脚本除文档重点介绍的三个脚本外同一目录下还有若干可直接组合使用的工具pluck.pypluck.py按where条件搜索并输出匹配对象的完整 JSON默认只输出第一个匹配项加--all输出全部。其输出经由CDDAJSONWriterutil.py重新排版对tools、components这类列表字段做了特殊的多行格式化。适合快速抽取某个物品的原始定义做参考。table.pytable.py将多个字段输出为 Markdown默认或 CSV 表格支持点号嵌套字段与--type过滤。例如table.py --typeARMOR id encumbrance coverage可生成护甲对比表对name.str、pocket_data.moves这类 i18n 对象字段脚本会优先取str/str_sp/str_pl等键中的首个有效值输出。jq/目录提供基于 jq 的统计脚本。例如count_json_entities.jq统计各类别实体数量用法见文件头注释$ jq -s -c -f tools/json_tools/jq/count_json_entities.jq $(find data/json -name *.json | grep -v obsolete)enumerate_json_entities.jq则将所有实体按type分组并把id、result、text、om_terrain、speaker等多种可能的标识字段统一映射为id输出适合生成实体清单。adjust_values.py、splitter.py、itemgroups.py等用于批量改写 JSON 数据的一次性脚本适合在数据迁移或大规模字段重命名时使用。使用前提与注意事项运行环境脚本面向 Python 3shebang 为#!/usr/bin/env python3。统计类工具无第三方依赖若需直接执行./keys.py请确保文件有执行权限否则用python3 tools/json_tools/keys.py调用。数据范围默认扫描 data/json 目录。若需分析模组数据data/mods可考虑将模组 JSON 目录软链或复制到临时位置或利用--fnmatch配合文件布局挑选范围——脚本目前仅内置了data/json一个数据根目录。输出格式默认 JSON 便于管道与程序消费--human适合人眼阅读--list适合提取去重集合。三者可组合使用。文档中的统计数字如 752 个 TOOL、25050 个 blob随版本演进会变化实际运行请以自己仓库当前数据为准。嵌套键限制values.py的-k目前最多支持一级点号下钻如pocket_data.max_item_length更深层的结构需配合 jq 或自写脚本处理。借助这套工具你可以把统计字段覆盖率枚举取值分布按条件查询 ID这类高频数据审查任务压缩成一行命令是维护 CDDA 内容数据时不可多得的效率利器。【免费下载链接】Cataclysm-DDACataclysm - Dark Days Ahead. A turn-based survival game set in a post-apocalyptic world.项目地址: https://gitcode.com/GitHub_Trending/ca/Cataclysm-DDA创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表