我在 Notion 里做了一个 GameJam 游戏库
Matrix 首页推荐
Matrix 是少数派的写作社区,我们主张分享真实的产品体验,有实用价值的经验与思考。我们会不定期挑选 Matrix 最优质的文章,展示来自用户的最真实的体验和观点。
文章代表作者个人观点,少数派仅对标题和排版略作修改。
当 Notion 遇到游戏,你觉得会撞出怎样的火花?在我这里,两者撞出了一个游戏库。
作为一个游戏爱好者,我发现自己总会被那些小巧的游戏作品吸引到。比如玩家们口中常说的独立游戏、或是那些诞生于 GameJam 的作品。
所谓 GameJam,可以理解为一种快节奏、鼓励创意表达的游戏开发活动,参加者或单人或组队抱团,需要在指定时间内从零开始制作出一个游戏,尽可能在游戏中表达一个特定的主题(通常由活动举办方指定),最终评选出优秀作品。(详情可以参考叶梓涛的 这篇介绍)
我曾在一次线下的游戏展会试玩过 GameJam 中诞生的作品,虽然完成度很难比得上 Steam 上陈列的那些游戏,但大多有巧妙的玩法设计,时不时就能遇到眼前一亮的宝藏作品,让我惊呼于开发者的创意和才能。
但线下的展会终归是有限制的,受限于路程、开放时间、人流量等各种因素,我很难自由试玩自己感兴趣的游戏,这也给我埋下了遗憾,总是忍不住关注类似的 GameJam 活动,想着多玩一些活动中诞生的游戏,但又会因各种原因无法如愿。
直到前不久,我在 机核网 的 App 里看到在推送一个叫 BOOOM 的活动,我突然回想起来,这就是那个给我埋下遗憾的 GameJam。我一个激动,便给自己定下了「体验完所有游戏」的目标。
但要体验所有的游戏,首先我得知道总共有哪些,这样才能持续追踪进度。经过随后的一系列折腾,我成功在当天内搭建好了一个 Notion 游戏库,收录完了这届 BOOOM 中所有游戏的信息。
在这篇文章中,我将回顾自己搭建这个游戏库的历程,如果你对数据收集、效率提升或信息管理感兴趣,或许也能为你解锁一些新知识,或是你熟知工具的新用法。
评估实现方案
如何收集数据?
在机核已经提供了 BOOOM 游戏列表 的情况下,数据的来源可以说是很明确了,直接从官方的页面中获取就可以。摆在开头的问题是:如何收集这些数据?收集后又要如何储存和呈现?
如果游戏数量不多,比如只有十几个,那我还可以考虑人工收集一下,但扫一眼 BOOOM 的页面便知,这次总共征集到了百余款作品。如果人工收集一个游戏要 1 分钟,怎么说也得两小时,而且这是一个高度机械重复的工作,很难保证做到中途会不会丧失动力和兴趣,因而我最好考虑更高效的方案。
恰好我对 Python 爬虫略有了解,便想到用爬虫来收集数据,这样不单单能了解「有多少个作品」,连每个作品相关的名称、类型、链接等信息都能一并收录。但是否能爬、如何爬,取决于目标网页的情况。
为此,我需要从爬虫开发的角度评估 BOOOM 的活动页面,我通常会关注的点包括:
- 需要哪些数据:比如文本、链接、图片,这部分会影响到数据提取的方式,以及后续如何储存这些数据
- 选用哪一种爬虫库:取决于页面数据的加载方式(静态/动态)、是否需要登录、爬取逻辑的复杂度(加载更多/自动翻页/跳转新页面)等,我通常考虑的库有 scrapy、selenium 和 requests
- 是否有可能不用写爬虫:比如如果能通过 Chrome Network 调试找到发送数据的请求、又比较方便手动构造是最好的,因为能拿到干净的 JSON 数据,而且又省事
经过一番观察,我有了初步的认知:
- 官方的 BOOOM 游戏列表表现为垂直滚动、动态刷新,似乎还带有随机排序
- 列表刷新是有限的,拖到最底部几次后就完全到底、不会再有新的出来
- 列表中每个游戏的信息,涵盖了标题、封面图(静态/动态)、标签,点击可以跳转游戏详情页
- 游戏的详情页,包含更多的图片(甚至视频)、文字描述(游戏介绍、下载方式、致谢词)、下载按钮(有的没有)、开发者信息(有的收录不全)
结论来说,可以爬,不过得想办法让爬虫模拟人滚动列表的操作,因为这部分的数据是动态加载、每次滚到最下面才会刷新。(具体做法见会在下面展开讲)
我也明确了要爬的信息,以及预想的用途:
- 游戏名称
- 封面图:便于视觉上快速辨别,作为封面也好看
- 标签:为寻找自己感兴趣的作品提供参考,或许也可以用于分析
- 链接:便于后续打开详情页看介绍、下载游戏和写评论
如何储存管理数据?
收集数据是可以交给爬虫了,但数据存在哪里?怎么查看和使用?
我很快想到了自己常用的 Notion,(少数派这里应该大多知道,但以防万一还是介绍一下)一款瑞士军刀般的笔记软件,集写作、计划、管理于一体,其中的数据库功能,提供了丰富的数据类型和视图预设,也支持筛选、排序、搜索,几乎完美匹配我对 BOOOM 游戏信息的管理需求。
定好了数据收集和储存的方案,我也列出了接下来要做的事:
- 编写爬虫收集数据
- 将数据导入 Notion
- 在 Notion 中配置视图
编写爬虫收集数据
前面我也提到过,因为官方的游戏列表是每次滚到最下面才会刷新的,我得想办法让爬虫模拟人滚动列表的操作,这样才能确保收集到全部的游戏数据。
我因此而选择了 selenium 库,一个常用于模拟人为操作、测试网页的库,用它来爬取动态页面简直不能更合适。
明确了技术方案后,我没有直接开始写代码,而是先自上而下拆解了任务,就像项目管理中的工作拆解结构(Work Breakdown Structure,WBS),我从一个脚本的目的起步,拆解出了每一步要解决的问题:
- 打开 BOOOM 网页
- 模拟滚动页面,加载完所有数据
- 遍历列表,提取所需的信息
- 将数据存入本地文件
明确了每一步的任务后,启动 Visual Studio Code(用来写代码的软件),新建了一个 Python 文件,然后用注释写明了脚本的目的、每一步要解决的问题。这部分参考了 Google 的 Python 代码注释规范,经过个人的实践,发现确实能避免不少回顾代码时的一脸懵逼。
有了这样大致的框架,接着就要逐个解决每步的问题了,具体的技术细节这里略过,基本是面向搜索引擎编程,考虑到可能有人会感兴趣,这里概括一下最终是如何实现的:
- 打开 BOOOM 网页:用 selenium 启动一个 Chrome 浏览器,打开 BOOOM 的活动页
- 模拟滚动页面,加载完所有数据:用 selenium 执行 JavaScript 脚本,获取网页滚动高度并模拟滚动,直至滚动高度不再增加
- 遍历列表,提取所需的信息:用 Xpath 表达式(一种用于在 XML 树状结构中定位节点的语言)定位网页中的每一个信息块,逐个遍历并继续用 Xpath 提取文本、链接等信息,存入列表套字典的结构里
- 将数据存入本地文件:用 pandas (一个常用于数据处理的库)将数据导出至 CSV 文件
最终写了 50 多行的爬虫代码(其中有不少是注释和排版用的空行),运行后便收集完了此次 BOOOM 所有游戏的数据。
爬到的数据导出到了本地的 CSV 文件,包含了 113 个游戏的这些数据:
- title:文本,游戏名称
- tags:列表,游戏打上所有标签
- game_url:文本,游戏详情页的链接
- img_url:文本,游戏封面图的链接
爬完了数据,按前面的计划,下一步就是把这些数据导入 Notion 了。
将数据导入 Notion
用过 Notion 的朋友可能会知道,Notion 的数据库功能是支持直接导入 CSV 的,导入后会自动补全不存在的列、设定好匹配的数据类型,但可惜的是我不能用这个功能。
问题就在于我收集的数据格式,有些是无法被 Notion 识别的,比如标签和图片链接。图片链接直接导入 Notion 会被识别为链接(URL 属性),而不是我希望看到的图片(Files & media 属性),这也意味着我之后要手动设置 100 多次图片数据,而不巧我是一个极度厌倦重复劳动的人。
于是新的问题摆在了面前,如何避免重复劳动将这批数据导入 Notion。我很快想到了 Notion API,Notion 官方为了方便开发者编写程序,将 Notion 与第三方工具打通、实现自动化而公开提供的一套接口。这时的我已经积累了一些使用经验、也打包了常用的函数,新写一个导入数据的脚本并不是什么难事。
类似写爬虫,我也拆解了这一环节的步骤,将数据导入 Notion 需要经历两步:
- 从本地文件读取数据
- 逐条遍历数据,在指定 Notion 数据库中新建页面
之后,针对每个步骤写代码实现:
- 从本地文件读取数据:用 pandas 读取 CSV 文件,得到 DataFrame 结构的数据
- 逐条遍历数据,在指定 Notion 数据库中新建页面:遍历每一条数据,提取各项信息并包装成 Notion 可接受的数据格式,用于新建页面
这里面比较头疼的是数据格式的转换,读取到的原始数据是一个个单独的变量,但为了让 Notion API 能正常使用这些数据,必须严格按照官方要求、重新包装成字典/列表层层嵌套的格式。
好在 Notion 为使用 API 的开发者提供了相对完善的文档,比如 这篇文档 就全面列举了各种数据类型的格式范例,让我了解了如何通过 Files 属性在 Notion 数据库中插入图片。
但写代码哪有一次就能跑通的,我也在插入图片这步踩了坑,的确是参考官方文档写的,但一个页面都没有添加成功,最后排查下来发现是图片链接有问题,Notion API 那边无法使用带后缀的图片链接,于是我又加了一步正则匹配处理,才得以解决。
在多次测试、修复完各种大小问题后,最终成功将数据导入了 Notion。
在 Notion 中配置视图
至此,Notion 的数据库中已经保存了这些信息:
- 游戏名称
- 标签
- 游戏详情页链接
- 封面图链接
尽管游戏库所需的数据都已经导入,但实际用起来还是会有不同的使用案例,因而还要从不同需求出发、设计对应的数据视图。
我从「体验完这届 BOOOM 所有游戏」的目标出发,列出了这些使用案例:
- 围绕体验进度跟踪作品
- 随机浏览作品、找找灵感
- 查看已体验作品的评分
列完后,我发现还需要建新的数据库,因为使用案例 1 和 3 都涉及到个人试玩作品的评分,而现有数据库管理的对象是游戏作品、不是评分,如果硬要将评分数据存在这边的数据库,会使得信息管理起来过于臃肿。
于是我又新建了一个「测评记录」数据库,根据试玩需要设计了数据模型:
- 游戏:关系,绑定到另一个数据库中对应的游戏,可以通过关系互相查表
- 表现力:数值,打分用
- 创新:数值,打分用
- 符合主题:数值,打分用
- 喜爱程度:数值,打分用
- 开始测评:时间,记录用
- 结束测评:时间,记录用
- 总评:文本,概括玩法+优缺点评价+总结
- 测评用时:公式输出数值,用开始和结束时间计算游玩了多少分钟
- 总分:公式输出数值,综合上面的几项打分计算总分,各项权重暂定均等
- 总分-图标化:公式输出文本,将总分转为 N 颗⭐的文本
再回到游戏的数据库,参考前面罗列的使用案例,通过组合 Notion 中的视图、筛选、排序、可见属性,我最终创建了 4 个不同的数据视图:
- 随机漫步:满足「随机浏览作品、找找灵感」的需求,以卡片呈现,显示封面、标题、标签、链接,伪随机排序(每分钟更新)
- 测评看板:满足「围绕体验进度跟踪作品」的需求,看板按进度分组,显示封面、标题、标签
- 已完成:满足「查看已体验作品的评分」的需求,以表格呈现,筛选已完成的、评分降序,显示所有属性
- 总表:临时搜索用,以表格呈现,显示所有属性
在随机漫步视图中,我用到了一套拍脑袋想出来的伪随机算法,刚好实现了每分钟重置一次列表排序。原理也很简单,每个作品的链接中有唯一的数字 ID(用正则从中提取),我在公式中代入当前的时间戳(精度是毫秒,但每分钟更新),用时间戳除 ID 取余数,最终每个作品就都会有一个每分钟更新、顺序不固定的数字,再用这个值来排序就可以。
分享到社区
到了这一步,我自己试玩所需的数据库已经算是搭好了,但我还准备额外做一个分享版,因为想起了自己用官方页面的痛点:
- 找特定的某个作品很难,往往要刷新出完整列表再 Ctrl+F(这时还不知道可以用机核的站内搜索)
- 浏览的连续性易被打断,随机排序时不时作品顺序就变了
既然我会有这样的痛点,说不定还有其他人也会有相同的体验,而这套游戏库应该也能帮到他们,发挥更大的价值。
很快,我复制了一份现有的数据库,重新配置了一套视图:
- 卡片:期望解决浏览不连续的痛点,卡片呈现,固定排序,显示封面、标题、标签、链接
- 随机漫步:满足随机探索需求,沿用现有的不变(老实说这又回到了官方的展示逻辑)
- 表格:满足搜索需求,表格呈现,显示所有属性
接着,通过 Notion 的分享功能,我将这个新游戏库公开分享到了网络,开启了评论、搜索引擎检索,然后在机核发了条动态带上分享链接,将其分享了出来。
最后
在发完那条动态后,我也有了一些意料之外的收获。
我收到了来自这届 BOOOM 开发者的点赞,游戏《Cato》的开发者 Blasin-Ree 在动态下评论,说这套 Notion 版的游戏库比官方的方便,让我着实高兴了好一会。
之后,《TRAiLS》的开发者 SleepyJeff 也找到了我,他帮我把这套游戏库的链接转发到了 BOOOM 开发者的群里,但发现有一个作品被漏掉了,可能是这组提交的比较晚、导致没被爬虫收集到。
我了解后,也去排查了一波,确认当时的官方列表里依然没收录到这个作品,于是帮忙手动补录了信息。这个作品是《斯巴拉西》,我之后试玩到发现美术很棒、完成度也很高的一个音游作品,希望这波补录能帮到他们。
还有一个意外收获,就是被一个叫西蒙的人关注了,我后来才知道,他是机核的创始人。
回顾这次的 BOOOM 游戏库搭建,我学到了这些:
- 爬虫收集的数据若需要持续访问使用,量级不大时可以考虑导入 Notion
- 在代码注释中点明目的,比点明做了什么更有助于帮助回顾
- 将围绕某个使用场景的常用函数打包,能让后续的开发更省事
- 涉及到重复操作 Notion 数据库时,可以考虑用 Notion API 做自动化
- 个人项目的产物可能也对他人有所帮助,多考虑分享
感谢 Blasin-Ree 的点赞、SleepyJeff 的热心联系,还有西蒙的关注,这次实践后,我发现自己不仅在知识输出上迈出了一步,也和独立游戏社区里的人们建立了更紧密的联系。
如果你也对这届 BOOOM 感兴趣,想试玩其中的游戏作品,可以访问 机核的活动页面,或通过我收录的 游戏库 寻找心仪的游戏。
这也是我在少数派的第一篇文章,如果这篇文章对你有所帮助,希望能点赞收藏一下,这是对我持续创作的最大支持。如果有其他想讨论的,也欢迎在评论区留下你的看法。
> 下载 少数派 2.0 客户端、关注 少数派公众号,解锁全新阅读体验 📰
> 实用、好用的 正版软件,少数派为你呈现 🚀