好几年前豆瓣有篇被转发了很多次的日记,一位用户为了更方便从Bandcamp 添加音乐条目到豆瓣而在淘宝找人花了一千块开发了个浏览器插件,只为了不再一一手动复制粘贴音乐信息。当时大家啧啧称奇都笑称这对豆瓣是真爱。没想到几年之后我踏上了同样的道路──实在是受够了豆瓣添加新书条目繁琐的操作。幸运的是现在不需要花一千块,利用好 AI 同样可以写出一个可用工具。

也看到过大行其道的各类所谓零基础「vibe coding」上架了个应用或是网站的文章,实际点进去查看发现作者要么是会其他编程语言,要么就是 tech 行业的产品经理或其他相关职位,每次都感觉被标题党了。所以这篇还想展示一下没有tech 教育背景、工作背景的人,怎么完成一个不算复杂的浏览器插件开发──没有那么难,但也并不轻松。 

起因

过去偶尔我也会为豆瓣创建条目但频率很低,像下面这样的页面忍受一下也就罢了。只是这一年多来由于阅读主题的转移,越来越多我读过的书豆瓣没有条目,这种重复劳动就实在让人厌烦。也看到过其他用户采取的方式是标记一个相同名字的条目在短评里说明是借地标记,这对我而言相当不能接受。而如果想要和中文用户(尤其我的友邻们)进行阅读互动,豆瓣显然还是无法绕过的平台。那就不如自己动手来写个工具,从Goodreads 上抓取图书信息添加到豆瓣。

 

豆瓣数十年如一日的“添加条目”页面

插件功能

  • 识别到当前页面为 Goodreads 书籍页时,在标题下增加「Add to Douban」按钮
  • 点击后抓取 Goodreads 书籍的标题、作者、出版时间、ISBN 等信息并跳转到豆瓣「添加书籍」页面
  • 在豆瓣页面点击按钮自动填写 ISBN 和标题
  • 在下一页面点击「Autofill More」自动填写标题、副标题、ISBN、作者(们)、出版社、出版日期、装帧、页数、内容简介
  • 拉到网页最底点击提交进入上传封面页面,点击按钮自动从 Goodreads 下载书籍封面并保存为书籍标题名,从本地文件夹选择文件上传。(不想下载封面可以跳过这步依然能够正常提交。)

至此新建条目的无数次复制粘贴操作可以直接简化成点击几次鼠标就能够完成。算上网页加载时间也只需几十秒,至多需要留意下信息是否有误(偶尔 Goodreads 的原始数据可能出错)。

 

 

安装链接:

  • Firefox:https://addons.mozilla.org/en-US/firefox/addon/good2dou/
  • Chrome:https://chromewebstore.google.com/detail/good2dou/jepndkfbipginmljbjmgnkpomhpdehid

开发(踩坑)过程

初始项目文件夹

非常流行的 Cursor 和 Claude code 因为付费和注册麻烦的缘故我都没有使用过,只在 VSCode 中使用了 GitHub Copilot Chat 扩展的 agent 模式,对于这么一个小项目已经绰绰有余。

流程相当简单,从 Goodreads 网站页面根据豆瓣需要的数据读取信息并保存,跳转到豆瓣再用 JavaScript 的 element query 选中对应元素设置数值即可。

在 VSCode 中新建一个项目文件夹,将目标页面(Goodreads 书籍详情部分、豆瓣新建条目的三个表单页)的 HTML 源码分别保存,再创建一个 readme 文件,详细写明操作逻辑、每一个页面需抓取或者填写的数据,在 chat 里 @ 上对应文件让它开始工作。

很快一个粗糙的第一版就出现了,但接着就发现一些数据无法直接使用,比如 Goodreads 网页上出版日期的是通常是 "November 4, 2025" 这种格式,而豆瓣的日期则只能选择数字。在脚本里写个转换 function 当然可行,可总觉得非常累赘,再仔细研究发现 Goodreads 页面上有完整的 JSON 数据包含书籍所有信息,这比一一用 document.querySelector 去筛选数据要靠谱得多──网页布局和属性说不定随时会被换掉,但数据结构通常不会大动。

而获取到数据后试图与豆瓣添加条目页面一一对应时不断发现新问题:

  • 标题
    Goodreads 不区分主副标题,豆瓣默认分开。Goodreads 上的标题格式可能是 title: subtitle,也可能是 series: title: subtitle,因此用 split 切分书名时选择从最后一个 “:” 切割而非第一个。
  • 作者
    豆瓣默认的作者栏只有三行,当作者数量大于三时必须手动创建新的输入框。
  • 日期
    豆瓣的日期填写是年月日格式的下拉框,无法一次性赋值,得用 setTimeout 逐一填写。
  • 书籍简介
    JSON 里的文本空格、换行、段落等格式无法直接复制粘贴到豆瓣的 plaintext 输入框中,只能再做一次转换处理。

将数据格式全部处理完成之后,油猴脚本终于可以使用了。但由于 tampermonkey 并不会自动在不同设备间同步,因此我想将它再改写成 Chrome 和 Firefox 插件上架插件商店。到这一步没想到浏览器扩展的 manifest 文件又是一个大坑,并且 Chrome 对此审核非常严格,每一个使用到的权限都需要详细陈述理由,并且插件上架还必须提供 icon、特定图片比例的插件截图,提供之后审核也需要几天时间,从最开始写到 Chrome 发布完成,零零散散花了快一周。

不过成就感也是无以伦比的(哪怕大部分工作都由 AI 完成),更让人满足的是它确实让添加条目的工作量大大降低了,短短一个月我在豆瓣添加的条目数量就已经超过了过去十几年的。有了 AI 后这类重复型的工作用它来开发辅助工具实在是再方便不过。

6
0