← 文章 / 科技资讯
Hacker News 7小时前 · 2026-09-20 08:23:39 · 4 阅读

Hacker News 排名算法解析:评分、争议惩罚与降权机制

Hacker News 的基本排序公式早已公开,但外界仍存诸多疑问。 公开代码中的公式是否就是真实算法? 排名究竟只取决于投票数,还是有其他隐形的影响因素? 涉及国家安全局(NSA)的新闻是否会被刻意压下去?为什么你在某篇热门文章下留了言之后,它就从首页消失了? 通过连续数天仔细分析 Hacker News 排名前 60 位的文章,我可以解答上述疑问,并揭示更多细节。 公开的公式大体准确。 排名的调整远比想象的多,首页文章中约有 20% 受到了不同程度的惩罚。任何标题中含有"NSA"的文章都会被降权并迅速下滑。一旦"争议性"文章评论数达到 40 条,就会受到严厉惩罚。本文详细阐述了评分机制和惩罚规则。[编辑:Hacker News 已不再惩罚 NSA 相关文章。] 文章评分基于点赞数、提交后的时间推移,以及各种惩罚因子,计算方式如下: score=\frac{ \left( votes-1 \right) ^{.8}}{ \left( age _{hours} + 2 \right) ^ {1.8}} * penalties 由于时间因子的指数高于投票数,文章的分数最终会归零,因此没有任何内容能长期占据首页。这个时间指数被称为老化因子。 你或许以为每次访问 Hacker News 时,系统都会根据上述公式重新计算所有文章分数并排序。但出于效率考虑,系统偶尔才对个别文章进行重新排名。当某篇文章获得点赞时,系统会重新计算其排名,将其移至合适位置,而保持其他文章排名不变。这样大幅减少了重新排名的计算量。然而,这也可能导致某些不再获得点赞的文章滞留在高位。为避免此问题,系统每 30 秒随机选取前 50 名中的一篇文章进行重新排名。结果是,如果一篇文章许久未获点赞,它可能会在较长时间内保持“错误”的排名。 此外,页面缓存时间可达 90 秒。 下图展示了 11 月 11 日全天 Hacker News 前 60 篇文章的原始分数(未扣除惩罚因子)。每条线代表一篇文章,颜色对应其在页面中的位置。 红线代表首页第一名。注意,由于惩罚机制的存在,原始分数最高的文章往往不是首页第一名。 Hacker News raw article scores throughout a day. Red line indicates the #1 article. Due to penalties, the #1 article does not always have the top score. 这张图表揭示了一些有趣的现象。文章分数会迅速飙升,随后在数小时内缓慢下滑。评分公式解释了其中很大一部分:若文章以恒定速率获得点赞,分数会迅速达峰后逐渐回落。但实际观察到的峰值上升得更快——这是因为文章通常在最初的一两个小时内获得大量点赞,随后点赞速率显著下降。这两个因素共同作用,形成了图中所示的陡峭曲线。 每天总有少数文章分数远超其他文章,中间段则分布着大量文章。有些文章分数很高,却因运气不佳被更热门的文章压在后面。另一些文章短暂登顶,夹在前一文章下滑和后一文章上升的空档中。 通过对比原始分数最高的文章(图表顶部)与实际排名第一的文章(红线),可以清楚看到惩罚机制的介入时刻。 某篇文章在早晨早些时候冲上第一名,但因争议性受到惩罚而迅速下滑,让另一篇文章短暂占据第一,随后被第三篇文章超越。 稍后,争议惩罚在另一篇文章刚登上一名时随即生效,导致其迅速跌出榜首。 某篇文章登上 Hacker News 顶端,却在上午 8:22 受到极重惩罚,直接跌出图表范围。 某篇文章人气极高,本可全天占据第一,却因迅速受到惩罚而滞留在第七名左右徘徊。 某篇文章一开始就因 NSA 关键词被惩罚,但人气太旺,仍夺得第一。不过随后它受到更严厉的惩罚,被迫下滑。直到临近晚间,某篇文章也被惩罚。事实证明,即使没有惩罚,它很快也会因另一篇文章的崛起而失去第一。 绿色三角形和文字标注了"争议"惩罚的生效位置。蓝色三角形和文字表示文章因惩罚跌落至前 60 名以外。较轻的惩罚未在图中标出。 很明显,Hacker News 首页第一名的内容并非自然竞争的结果,而是对许多文章持续施加惩罚的产物。尚不清楚这些惩罚是出于管理员操作还是用户举报。 部分提交内容会因标题自动受到惩罚,另一些则因域名被惩罚。 标题中若含有特定敏感词,会自动获得 0.4 的惩罚因子。我查找了其他可能触发自动惩罚的词汇,但发现它们似乎不受此限。 我观察到,许多网站似乎会自动受到 0.25 到 0.8 之间的惩罚因子: arstechnica.com, businessinsider.com, easypost.com, github.com, imgur.com, medium.com, quora.com, qz.com, reddit.com, rt.com, stackexchange.com, theguardian.com, theregister.com, theverge.com, torrentfreak.com, youtube.com。实际名单肯定更长。(这与"禁止收录的网站"不同,后者曾在特定时期被完全屏蔽。) eterm 指出的一种可能性是:来自热门媒体的新闻往往被多人同时提交,导致其获得的点赞数超出文章本身"应得”的水平。自动惩罚热门网站有助于抵消这种效应。 利用评分公式,可以计算惩罚因子的具体影响。若惩罚因子为 0.4,相当于每个投票只计 0.3 票。换言之,文章排名下滑速度比正常快 66%。惩罚因子为 0.1 时,相当于每个投票只计 0.05 票,或排名下滑速度为正常的 3.6 倍。因此,0.4 的惩罚因子已有很显著影响,而 0.1 则极为严厉。

争议惩罚 为防止 Hacker News 上演口水战,评论数"过多”的文章会被作为"争议性”内容受到重罚。 在公开代码中,contro-factor 函数对评论数超过 20 条且评论数多于点赞数的帖子生效。此类文章的分数会被乘以 (点赞数/评论数)^2。然而实际公式有所不同——它对任何评论数多于点赞数且至少达到 40 条评论的帖子生效。根据经验数据,我猜测指数是 3 而非 2,但尚未证实。 争议惩罚可能对文章排名产生突发且灾难性的影响,导致文章前一分钟还排名靠前,一旦达到 40 条评论便瞬间消失。如果你曾疑惑为何某篇热门文章突然从首页消失,争议惩罚很可能是主因。 例如, Why the Chromebook pundits are out of touch with reality 在达到 40 条评论的瞬间从第 5 名跌至第 22 名,而 Show HN: Get your health records from any doctor' 原本排在第 17 名,在达到 40 条评论后彻底跌出前 60 名。

我的研究方法

我每分钟抓取一次 /news/news2 页面(控制在每分钟 2 页的规范以内)。我用 Beautiful Soup 解析那些(有点乱糟糟的)HTML,再用一大堆 Python 脚本处理结果,最后用难以看懂但功能强大的 matplotlib 画图。 分析的基本思路是:先用公式算出原始分数,再寻找异常值。在某个时间点(比如 11 月 9 日 8:46),可以算出排名前 10 的帖子的原始分数:
2.802 Pyret: A new programming language from the creators of Racket
1.407 The Big Data Brain Drain: Why Science is in Trouble
1.649 The NY Times endorsed a secretive trade agreement that the public can't read
0.785 S.F. programmers build alternative to HealthCare.gov (warning: autoplay video)
0.844 Marelle: logic programming for devops
0.738 Sprite Lamp
0.714 Why Teenagers Are Fleeing Facebook
0.659 NodeKnockout is in Full Tilt. Checkout some demos
0.805 ISO 1
0.483 Shopify accepts Bitcoin.
0.452 Show HN: Understand closures
注意排名前十的文章中,有三篇的实际排名低于其分数所对应的预期位置:《纽约时报》、Marelle 和 ISO 1。由于《纽约时报》排在得分分别为 1.407 和 0.785 的两篇文章之间,其惩罚因子可在 0.47 到 0.85 之间计算得出。同理,另外两篇文章的惩罚因子范围分别为 0.87 到 0.93 以及 0.60 到 0.82。 我观察到,大多数文章的排名都与其得分相符,而那些例外情况则普遍被排到了低得多的位置,这表明存在惩罚机制。这一现象说明,当前使用的评分公式与公开的代码一致。如果公式有所不同,例如引力指数更大,随着投票数或时间的增加,文章的排名会偏离“预期”位置,但我从未看到这种情况发生。 这种技术证实了惩罚机制的存在,并给出了惩罚值的范围,但确定精确的惩罚值却十分困难。你可以随时间观察这个范围,希望它收敛到一个单一值。然而,几个误差来源干扰了这一过程。首先,邻近的文章可能也受到了惩罚,或者评分方式不同(例如招聘广告)。其次,由于文章并非时刻被重新排序,某篇文章可能暂时处于不当的位置。第三,文章上的惩罚可能会随时间变化。第四,报告的投票数可能与实际投票数不同,因为“恶意”投票会被抑制。结果是,我只能确定大致的惩罚值,但数值上存在相当的不稳定性。

一日内惩罚情况

下图展示了一天内计算出的惩罚值。每条线代表一篇文章。它应从 1(无惩罚)开始,当惩罚被应用时,线条会降至相应的惩罚水平。当文章跌出前 60 名时,线条结束,这通常发生在惩罚应用后的不久。似乎存在 0.2 和 0.4 的惩罚,还有大量在 0.8 到 0.9 之间的惩罚。看起来很多惩罚在上午 9 点(管理员上线的时间?)被应用,全天也陆续有更多惩罚。由于图表噪点较多,我正在尝试不同的算法来改进它。
平均来看,首页约有 20% 的文章受到过降权,而第二页这一比例升至 38%。由于受降权文章本来就更难出现在首页,首页的比例自然偏低,这在某种程度上符合定义。实际发生的降权情况比大多数人想象的要频繁得多。 以下是 11 月 11 日首页列表中所有受过降权的文章。(该列表排除了那些若未受降权本会上首页的文章。)这份名单比我预想的长得多,向下滑动即可查看完整内容。

气候公司为何把自己卖给孟山都Facebook 出版社比尔·盖茨:我在抗击小儿麻痹症之中学到了什么麦凯恩称 NSA 局长 Keith Alexander“应该辞职或被解职”你不是软件工程师什么是 Y 组合器?台风海燕致菲律宾上万人遇难想说服别人,就给他们讲个故事俄罗斯方块与 CSS 的力量微软研究院论文库莫斯科地铁:做 30 个深蹲换免费车票货轮的隐秘世界Rust 这些周空腹的智慧把网站注册流程彻底做错了代码的六大物种亚马逊将在邮政协助下启动周日配送Linux 吃掉了我的内存用 CSS 画辛普森一家苹果地图:所有人都以为谷歌赢了的那个时刻,它其实已经输了Docker 与 Go:我们为什么决定用 Go 写 Docker?亚马逊代码忍者最后几位杜立特空袭队员举杯作别Linux Voice——一本回馈社区的新 Linux 杂志想下载动漫?我刚写了个程序花 15 分钟向陌生人解释你为什么热爱自己的工作为什么你永远不该用 MongoDBShow HN:SketchDeck——更快地做幻灯片78 秒从零到装好带 Peanut Butter 的 DockerNSA 的监控权限远不止反恐Sentry 开源服务的诞生故事Real World OCamlShow HN:从任何医生那里获取你的健康档案为什么 Chromebook 的评论家们脱离现实迈向 JavaScript 库更加模块化的未来virt-builder 为什么用 OCaml 写?iOS:一个时代的终结能插进 iPhone 耳机孔的最疯狂的东西RFC:用 Go 替换默认语言中的 JavaShow HN:在 Health Sherpa 上找到你的健康保险方案Web Latency Benchmark:一种全新的浏览器基准测试亚马逊、Facebook 和雅虎为什么都在抄微软的末位淘汰制?与 NSA 切断联系医生戴着 Google Glass 做手术Duplicity + S3:简单、便宜、加密、自动化的全盘备份Bitcoin 在英国的前景堪忧Amazon Redshift 的新功能你听到的只是好听的那部分反馈软件很简单,硬件难度中等Adobe 泄密事件后 Facebook 向用户发出警告国际空间站感染 U 盘恶意软件Tidbit:客户端 Bitcoin 挖矿Go:"这个名字我已经用来给我的* own *编程语言了"多模式无人机:能飞、能游、能跑Go 语言日报"我们没有食物,我们需要水和其他东西才能活下去。"Humble Store 亮相代码的六大物种中国 Bitcoin 交易平台 GBL 消失,410 万美元不翼而飞Bitcoin 会比互联网更具颠覆性吗?Apple Store 正在更新中

评分公式的代码

HN 服务器某版本对应的 Arc 源代码可供获取,同时还有更新后的评分公式
  (= gravity* 1.8 timebase* 120 front-threshold* 1
       nourl-factor* .4 lightweight-factor* .17 gag-factor* .1)

    (def frontpage-rank (s (o scorefn realscore) (o gravity gravity*))
      (* (/ (let base (- (scorefn s) 1)
              (if (> base 0) (expt base .8) base))
            (expt (/ (+ (item-age s) timebase*) 60) gravity))
         (if (no (in s!type 'story 'poll))  .8
             (blank s!url)                  nourl-factor*
             (mem 'bury s!keys)             .001
                                            (* (contro-factor s)
                                               (if (mem 'gag s!keys)
                                                    gag-factor*
                                                   (lightweight s)
                                                    lightweight-factor*
                                                   1)))))
如果你不熟悉 Arc 代码,以上代码片段定义了几个常量,例如 gravity* = 1.8timebase* = 120(分钟)等。随后它定义了一个方法 frontpage-rank,该方法根据文章的点赞数(realscore)和以分钟计的发布时间(item-age)对文章 s 进行排序。 惩罚系数由一个包含多个分支的 if 语句定义。如果文章类型不是 'story' 或 'poll',惩罚系数为 0.8。否则,若 URL 字段为空(例如 Ask HN 帖子),则系数为 nourl-factor*。如果文章被标记为 'bury',缩放系数设为 0.001,实际上意味着该文章会被彻底隐藏。最后,默认情况下,该系数将争议因子与恶搞/轻量级因子相乘。 争议因子 contro-factor 旨在压制那些容易引发激烈争吵的文章,后文将进一步讨论。 下一个因子会对被标记为恶搞(joke)的文章施加 0.1 的重惩罚值,而对“轻量级”文章则施加 0.17 的系数。实际的惩罚体系似乎比公开代码中展示的更为复杂。

结语

Hacker News 首页上的文章位置,并不如你想象中那样完全基于点赞数。 通过仔细研究出现在 Hacker News 页面上的文章,我们可以深入了解其评分公式的工作机制。虽然点赞数是影响排名的明显因素,但还存在一套复杂的“惩罚”系统,它会导致文章排名下降,甚至彻底消失。这套系统的作用不仅仅为了防止垃圾信息,还影响着许多非常热门的文章。此外,如果某篇文章的评论数超过了点赞数,请不要再添加评论,否则可能会彻底让这篇文章“死掉”! 参见 Hacker News 上的讨论:Hacker News

更新(11月18日):关于惩罚的文章也受到了惩罚

颇具讽刺意味的是,这篇关于惩罚机制的文章在 Hacker News 上也受到了惩罚。在登上首页后的几分钟内,一个重达 0.2 的惩罚系数被施加到这篇文章上,导致它被强制移出首页。下图中的黑线显示了这篇文章在 Hacker News 上的排名位置。你可以看到,在惩罚生效时排名出现了急剧下降。灰线则显示了如果没有惩罚,这篇文章本该达到的排名。如果没有惩罚,这篇文章本可以排在第 5 位,但由于惩罚的存在,它再也没有回到首页(第 1-30 位)。下方的绿线显示了这篇文章的原始分数。(11月26日:我被告知,这个惩罚是因为“投票环检测”系统错误触发。)
这篇文章在登上 Hacker News 首页后不久就受到了惩罚

原始来源: Hacker News

评论 (0)