Refactoring English: Month 20

Michael Lynch

重构英语:第 20 个月

原文由 Michael Lynch 发布,订阅该博客

一句话总结

图书销量增长至三倍,同时还在与爬虫机器人较量。

初来乍到?

嗨,我是 Michael。我是一名软件开发者,也是小型独立科技公司的创始人。目前我正在写一本书,名叫Refactoring English: Effective Writing for Software Developers

每个月,我都会发布一篇像这样的回顾,分享新书以及整体职业生涯的近况。

亮点

  • 7 月的图书销量达到了 6 月本已强劲销量的三倍。
  • 我正在对抗全世界最蠢的爬虫机器人。
  • 我正在用 AI 制作一款多人浏览器游戏。

目标完成情况

每个月初,我都会定下当月想要完成的目标。以下是完成情况:

向 5 档播客自荐,聊聊Refactoring English

  • 结果:只向一档播客发出了自荐
  • 评分:D

我花了不少时间准备向Talking Postgres自荐,结果发现主持人除了 LinkedIn 之外没有留下任何联系方式。于是我在 LinkedIn 上给她发了私信,但始终没有收到回复。我倒是做客了The TMPDIR Podcast,不过他们在我自荐之前就已经邀请了我,所以不能算数。

Refactoring English网站吸引 3 万名独立访客

  • 结果:网站有 2.38 万名独立访客
  • 评分:B

我心里其实是把这个目标当成了“有一篇文章登上 Hacker News 首页”,虽然做到了,却依然没能达到 3 万访客。

结束抢先体验,发布图书 1.0 正式版

  • 结果:仍未发布 1.0 正式版
  • 评分:D

结果我花在回应用户反馈上的时间超出了预期。我的反馈应用运转良好,但它也会带来难以预料的新工作量。

Refactoring English数据

指标2026 年 6 月2026 年 7 月变化
独立访客17,52323,817+6,294 (+36%)
预售收入$1,441.86$3,908.80+$2,466.94 (+171%)

6 月是自 Kickstarter 众筹以来图书销量第二高的月份,而 7 月的销量则是 6 月的三倍。

销量大涨的主要原因是,我结束了抢先体验的优惠。我在 7 月 13 日宣布抢先体验价将于 7 月 20 日结束,价格将从 30 美元涨至 49 美元。

销量图表,显示 7 月 20 日出现峰值,此后销量放缓

在促销的最后一天,我发布了一篇题为《“Why I Stopped ‘Creating Content,’”》的博客文章,它登上了 Hacker News 首页。随后,它又成了bubbles.town 当天的热门第一,这是一个类似 Hacker News、但更偏独立、较少以技术为中心的网站。

促销最后一天出现了巨大的销量峰值,仅当天就卖出了超过 1000 美元。

我把价格提高到 49 美元后,销量迅速下滑,这也在我的预料之中。我计划在图书正式发布 1.0 版本后,再进一步尝试不同的定价策略。

我在对抗全世界最蠢的爬虫机器人

我在周一发布了博客文章,访客量大幅上涨。然后到了周二,又出现了一次巨大的激增:

看到访客量暴涨时,我还以为是某个知名博主转载了我的文章,后来才意识到这肯定是机器人干的。

所有访客都在访问Hacker News Popularity Contest。以前也出现过博主谈论自己在比赛中的排名并链接到我的工具,从而带来一波访客的情况,但从未有过这么大的规模,也从未如此持久。

看到第二次峰值时,我还想:“哇,这周真是顺风顺水!”我正跟妻子说这事,突然恍然大悟:

今天又来了五万访客!我都不知道他们是从哪儿来的,猜测可能是有人发了推文。

嗯,其实如果有人发了推文,我应该能在来源里看到 Twitter。

哦……是机器人。

我查看了日志,发现所有请求都使用了完全相同的浏览器 User Agent:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36

这是 Chrome 125,一个已经发布两年多的浏览器版本。这个版本号让识别机器人变得很容易,因为阅读我博客的真人用户不太可能还在用这么旧的浏览器。

这个爬虫似乎只是在反复加载比赛主页,然后一遍又一遍地点击每一个链接,于是我想跟它耍点小聪明。我在 Bunny 上放了一个重写脚本,会检查 User Agent,如果是这个爬虫就返回一个假的响应。这样一来,原本会生成 3000 多个链接的页面,就只会生成三个链接。

不知为何,我的假响应没有起作用。我怀疑爬虫已经把全量的 URL 都存进了数据库,所以在首页隐藏它们根本没用。

我尝试了限速,但 Bunny 支持的最低限速是 1 KB/s,而我应用的大部分数据都是只有几 KB 的小文件。爬虫还在大约 100 个不同的 IP 段之间轮换,所以也无法按 IP 限流。

最后,我直接按 IP 段进行了封禁。我用 vibe coding 做了一个工具,会扫描 Bunny 日志中特定的 User Agent,并收集与这次攻击相关的所有 IP。这个方法奏效了,但一周后攻击又卷土重来,换了新的 IP 和一个稍新的 User Agent,于是我重新运行脚本、更新了封禁 IP 列表,目前看来是有效的。

这次攻击最诡异的地方在于,这些机器人根本不在乎被封禁。它们还是不停地猛攻服务器。我本以为它们会想:“都已经在 TCP 层面被 100% 拦截两周了,再浪费算力和带宽发请求也没意义”,但它们显然毫不在意。

即使我已经封禁了攻击者的 IP,它们仍在不停地发起请求。

攻击开始当天我就联系了 Netlify 的客服,但毫无用处。每一次回复都要等上一周。我觉得第一次回复是 AI 生成的,因为它让我去修改一些根本不存在的设置。第二次回复看起来更像是真人,但意思基本是:“看起来你在我花两周时间回复的期间已经自己解决了问题,所以也没什么需要我做的了!”好在在我提出要求后,他们还是退还了 55 美元的超额费用。

静态网站还能托管到哪里?

我的所有静态网站都托管在 Netlify 上,他们的服务一直在走下坡路,而他们对这次爬虫机器人攻击的完全漠视,更让我下定决心要找一家能更主动应对爬虫的服务商。

最现成的答案是“Cloudflare”,但我对互联网基础设施如此高度集中于 Cloudflare 感到担忧,所以不想再进一步加剧这种集中化。

我也考虑过直接用 VPS,或者用 VPS + Bunny 做 CDN 来托管,但我不想在登上 Hacker News 首页的那天,因为 VPS 宕机或我在 Bunny 上配错了缓存而导致网站掉线。我想要的是一种只要付费、就有人帮我保证网站在线的方案。

  • Surge
    • 优点
      • 专注于静态托管,这正是我想要的
      • 不限流量,因此由他们承担爬虫攻击带来的成本
    • 缺点
      • 似乎由一个人运营(我猜的),因此宕机风险更高
      • 所有管理都要通过他们的命令行工具完成,没有网页后台
      • 看起来不支持多因素认证,不过似乎正在开发中
      • 上传时会无条件上传所有文件,而不是像 rsync 那样只同步有变化的文件,这对我那些只有增量变化的大型站点来说很麻烦
  • statichost
    • 优点
      • 由一个人运营,所以客服响应迅速、也很周到
      • 主要专注于静态托管,没有多余的复杂功能
    • 缺点
      • 由一个人运营,因此宕机风险更高
      • 上传时会无条件上传所有文件,而不是像 rsync 那样只同步有变化的文件,这对我那些只有增量变化的大型站点来说很麻烦
      • 不包含防爬虫保护
      • 将站点构建和托管打包在一起,但我只需要托管
      • 一大卖点是以欧盟为中心,但我在美国
  • Vercel
    • 优点
      • 声称能防范 DDoS/爬虫机器人
      • 我觉得他们支持类似 rsync 的上传方式
    • 缺点
      • 庞大而复杂的服务
      • 我没有理由相信 Vercel 会比 Netlify 对我更好
  • 在 Bunny CDN 之上自建方案
    • 我考虑过这个方案,但在 Bunny 上实现增量上传和原子化部署本身就是一个复杂的项目

Mikeville:我那款未完成的多人浏览器游戏

我一直在捣鼓一台小型的云服务器,它有 4 核 CPU 和 8 GB 内存,但大部分时间都在闲置。既然手头有台性能不错、还有富余的服务器,能给朋友们托管点什么好玩的东西呢?

做个游戏怎么样?我见过像ValheimARK这样可以自托管的游戏,但感觉那些游戏需要其他玩家同时在线才好玩,否则就没什么意思。

作为一个几个月才玩一次电脑游戏的人,我想要的是一种既能在其他人同时在线时进去一起玩得很开心,即使我不在场,也能看到期间发生了什么、依然觉得有趣的体验。我脑海中的感觉,就像是和朋友们共同拥有一栋海边小屋,有时一起去度假,有时各自单独去时,会给对方留下字条和礼物。

问题是,我想不出该如何把这种“海边小屋”的感觉,转化成一个具体的游戏概念。

目前,我正在体验用 vibe coding 做游戏是什么感觉,看看什么玩法会让人觉得有趣。设计这个原型时,我脑海中的两款参考游戏是《星露谷物语》和《网络创世纪》,这两款游戏我都玩了很长时间。

如果你想在浏览器里试玩,游戏已经上线:

今天我会在线一小会儿,欢迎来逛逛。源码目前放在 GitLab 上,等找到更好的 Git 托管平台再搬家。

我喜欢的几篇博客文章

  • Stripe Just Wants a Number
    • 我很喜欢 exe.dev 这个博客,他们思考问题的方式很有意思,尤其是那些影响小型软件厂商的软件问题。我的计费逻辑还没复杂到需要用上这个方案的程度,但原则上我觉得这个想法很巧妙。
  • 99% of My Website Traffic Is Bots
    • 考虑到我这个月与爬虫机器人的交手经历,这篇文章让我很有共鸣,也很有帮助。我也很喜欢其中的定制插图。
  • I Regret Migrating to Codeberg
    • 过去一年里,我一直在把项目从 GitHub 迁移到 Codeberg,而且还是付费会员,但现在我后悔在这个平台上投入了。总是出现各种宕机,经常服务器过载。压垮骆驼的最后一根稻草是 Codeberg 决定封禁使用 AI 的项目。我大概还没超过“过度使用 AI”的那个模糊门槛,但我还是打算搬到别处去。
  • Super Mario Derivations
    • 这是一个很巧妙的 Nix 技巧,作者用 Nix 属性来编码《超级马里奥 3》模拟器中的游戏状态,比如 nix build '.#level1.rightb.rightb.rightab.rightb' 表示从第一关开始,依次按下 Right + B(向右跑)两次、Right + A + B(跑跳)、再按一次 Right + B(向右跑)。Nix 会缓存所有的游戏状态,所以你改动某个按键操作时,只需要重新计算与之前不同的部分。

收尾

下月目标

  • 向 5 档播客自荐,聊聊Refactoring English
  • Refactoring English网站吸引 3 万名独立访客。
  • 发布图书的 1.0 正式版。

求助

  • 如果你有静态网站托管方面的推荐,欢迎告诉我。
  • 如果你认识Claire Giordano,请告诉她我很适合做客Talking Postgres(聊的是技术写作,不是 Postgres)。

本文章由 muse-spark-1.2-contributor 进行翻译

评论