← 返回蜂巢洞察

如何利用pub.dev API开发用于分析Dart包的使用情况的工具:超越30天的时间限制

当我把我的软件包发布到pub.dev上时,最初的几天真的很令人兴奋,因为下载量一直在上升。短短几天内就收到了201次下载请求! 但随后发生了一些奇怪的事情:下载量开始下降——先是降到了120次,然后又降到了55次。就在那时,我意识到有些事情不对劲了。 我没有破坏任何东西,软件包本身也没有任何变化,人们也没有停止使用它。 问题出在统计的时间窗口上。 这就是我对pub.dev最不理解的地方之一:它显示的30天累计下载量其实并不是总数,也不是累积计数,而只是一个时间窗口内的数据。当那些最初带来大量下载量的用户在这个时间窗口之外时,你的下载量就会下降,尽管这些用户仍然在使用你的软件包。 这个发现让我开

当我把我的软件包发布到pub.dev上时,最初的几天真的很令人兴奋,因为下载量一直在上升。短短几天内就收到了201次下载请求!

但随后发生了一些奇怪的事情:下载量开始下降——先是降到了120次,然后又降到了55次。就在那时,我意识到有些事情不对劲了。

我没有破坏任何东西,软件包本身也没有任何变化,人们也没有停止使用它。

问题出在统计的时间窗口上。

这就是我对pub.dev最不理解的地方之一:它显示的30天累计下载量其实并不是总数,也不是累积计数,而只是一个时间窗口内的数据。当那些最初带来大量下载量的用户在这个时间窗口之外时,你的下载量就会下降,尽管这些用户仍然在使用你的软件包。

这个发现让我开始深入探究:如果pub.dev只显示30天内的数据,那么有没有办法看到更完整的统计结果呢?是否存在可以提供更多信息的API?pub.dev实际上是如何进行数据统计的?

这篇文章就是关于我的这些探索,以及我根据这些探索开发出来的工具。

目录

30天时间窗口的问题

当你把软件包发布到pub.dev上时,该平台会显示一个下载量数字。如果你现在查看任何一个软件包页面,都会看到一个标有“下载次数”的数值。大多数开发者都认为这个数字就是他们的软件包自发布以来被下载的总次数。

但实际上并非如此。

pub.dev显示的是过去30天内的累计下载量。它只记录在这30天内你的软件包被下载了多少次,之前的数据都不会被计入其中。

举个实际的例子来说:当你发布了一个软件包后,在Twitter、LinkedIn以及开发者社区里分享了它,第一周内下载量可能会激增,达到200次。但之后下载量就会下降,也许一周后只剩下10次下载。

在发布初期,200次下载量会被显示出来;5周后,只有过去30天内的50次下载量会被显示;而10周后,可能就只剩下40次下载量了。

这个数字下降了75%,但你的软件包并没有被丢弃或损坏,而是被那些已经安装了它的200个人在默默地使用着。下载量仍在持续增加,只不过增长速度比最初那段高峰期要慢一些而已。

窗口发生了变化,那个数据点也因此从显示区域中消失了。但pub.dev上显示的数据却让人误以为你的包的下载量在下降。

对于那些一直在关注自己包的下载量变化的人来说,这种显示方式确实具有误导性。

pub.dev实际上是如何计算下载量的

在了解相关的API之前,我们首先需要明白pub.dev究竟是如何统计下载次数的。

pub.dev记录的是某个包的压缩文件从其服务器上被下载的次数。当你在项目中运行pub get或flutter pub get命令时,pub工具会先检查你本地的PUB_CACHE文件夹。如果该包已经存在于缓存中,系统就会直接使用缓存中的版本,而不会再次进行下载;只有当包不在缓存中时,才会被真正下载下来。

这意味着,下载次数并不能反映有多少个项目正在使用你的包,它实际上反映的是开发者们需要从服务器上重新获取该包的频率。例如,如果有1000位开发者都在使用你的包,但他们都已经将这个包缓存在本地了,那么在这段时间内,该包的下载次数就会显示为0。

pub.dev对此已经做出了明确的说明。在他们发布的官方文档中写着:“下载次数并不能直接反映一个包被多少用户使用。由于pub客户端会将下载内容缓存到PUB_CACHE中,因此某个包的下载次数可能会低于其实际使用频率。”

所以你在pub.dev上看到的数字实际上已经是对实际使用情况的低估;而且,这个数字还只反映了过去30天内的情况。

pub.dev背后的API

当我意识到pub.dev所显示的数据其实只是部分信息时,我首先就去寻找那些能够提供更多详细信息的API。pub.dev在官方API文档页面上提供了相关的说明。让我们一起来看看那里都记录了哪些内容。

评分接口

GET https://pub.dev/api/packages/{package}/score

这个就是生成你在pub.dev上看到的下载次数的官方接口。你现在就可以亲自尝试调用它:

curl https://pub.dev/api/packages/dart_exceptor/score

响应结果如下:

{
  "grantedPoints": 150,
  "maxPoints": 160,
  "likeCount": 5,
  "downloadCount30Days": 174,
  "tags": [
    "sdk:dart",
    "sdk:flutter",
    "platform:android",
    "platform:ios",
    "platform:linux",
    "platform:macos",
    "platform:web",
    "platform:windows"
  ]
}

downloadCount30Days就是pub.dev在包页面上显示的下载次数。这个数字代表的是过去30天内的累计下载量,没有其他含义。

likeCount表示有多少开发者喜欢了这个包。

grantedPoints和maxPoints则是来自pana分析器的评分结果。

这个接口端点得到了官方的支持,并有正式的文档记录。在没有另行通知的情况下,它不会发生任何变化。

包元数据接口端点

GET https://pub.dev/api/packages/{package}

curl https://pub.dev/api/packages/dart_exceptor

这个接口端点是“托管Pub仓库规范V2”的组成部分,而pub命令行工具本身也是通过这个规范来查找和下载包的。它能够返回完整的包元数据:每个已发布的版本信息、每个版本的包描述文件、发布时间戳,以及该包的其他详细信息。

PubTrace就是利用这些信息来确定一个包是何时首次被发布的。如果一个包是在六周前发布的,那么它的历史记录也只有六周的时间,而不是52周。相关文章应该如实说明这一点。PubTrace会从这个接口端点中读取第一个发布日期,并用它来准确标注图表中的数据。

响应返回的数据量较大。对于PubTrace来说,其中一些重要的字段包括:

{
  "name": "dart_exceptor",
  "latest": {
    "version": "1.1.2",
    "published": "2026-07-12T10:00:00.000Z"
  },
  "versions": [
    {
      "version": "1.0.0",
      "published": "2026-07-01T10:00:00.000Z"
    }
  ]
}

发布者接口端点

GET https://pub.dev/api/packages/{package}/publisher

curl https://pub.dev/api/packages/dart_exceptor/publisher

响应结果:

{
  "publisherId": null
}

而对于经过验证的发布者来说,响应结果会如下所示:

{
  "publisherId": "dart.dev"
}

PubTrace会利用这些信息来显示该包是由谁制作的。如果一个包属于经过验证的发布者,就会显示相应的发布者信息;否则,上传者的身份就会被标记为“未经验证”。

这个接口端点得到了官方的文档记录和正式支持。

指标数据接口端点:详细信息

在这里,事情就变得有趣起来了。

在探索pub.dev的公开接口时,我发现了一个并未被收录在官方API文档中的接口端点,但这个端点是可以被公众访问的,而且pub.dev本身也在内部使用它:

GET https://pub.dev/api/packages/{package}/metrics

curl https://pub.dev/api/packages/dart_exceptor/metrics

pub.dev明确指出了这一点。在他们的官方API文档中写着:“pub.dev可能会提供一些可供公众使用的API接口端点,但除非这些端点被记录在这里,否则我们并不认为它们得到了官方支持,因此我们也可能在没有事先通知的情况下对它们进行修改或删除。”

指标数据接口端点就属于这类接口。它是公开的,任何人都可以调用它。但它并没有得到官方的支持,这意味着它的内容可能会发生变化。不过PubTrace仍然在使用它,因为这是获取相关数据的唯一来源,而且从这个接口端点获得的每一项数据都可以通过终端设备进行独立验证。

这个端点返回的响应中包含一个scorecard对象,其中包含了weeklyVersionDownloads这一数据项。pub.dev自身所使用的每周统计图表就是依据这些数据生成的。该数据项共有52条记录,分别对应过去一年中的每一周,记录是按时间顺序排列的,最新的记录排在最前面。每条记录都会详细划分不同版本范围内的下载情况:总下载量、重大版本范围的下载量、次要版本范围的下载量,以及补丁版本范围的下载量。

相关数据的简化格式如下:

{
  "scorecard": {
    "weeklyVersionDownloads": {
      "totalWeeklyDownloads": [45, 38, 62, 71, 28, 19, 33, ...],
      "majorRangeWeeklyDownloads": [...],
      "minorRangeWeeklyDownloads": [...]],
      "patchRangeWeeklyDownloads": [...]
    }
  }
}

这个数组一共有52条记录,其中索引为0的代表最近一周的数据,索引为51的代表数据集中最古老的一周。

在pub.dev的界面中,totalWeeklyDownloads显示的是最近大约4周的数据总和(也就是大约30天的数据)。而实际上API响应中包含了全部52条记录,但这些数据在pub.dev的界面中是无法被看到的。

正是看到了这一点,我决定自己开发一个工具来解决这个问题。

开发PubTrace

当我弄清楚了这个数据端点提供了哪些信息之后,我就想到了这样一个问题:既然每次想要查看某个包的下载历史记录时都不得不手动调用这些API,那么为什么不开发一个整个Dart和Flutter社区都能使用的工具呢?

就这样,PubTrace应运而生了。

PubTrace是一款免费的工具,它可以显示任何在pub.dev上发布的Dart或Flutter包在52周内的完整下载历史记录。使用PubTrace不需要注册账户,也无需进行任何登录操作。你只需访问pubtrace.dev,输入相应的包名,就能看到pub.dev界面中没有展示的那些详细数据。

PubTrace的功能

pubtrace.dev显示了非常受欢迎的Flutter包‘DIO’的下载量统计

PubTrace是一款免费且开源的工具,你可以通过https://pubtrace.dev访问它。输入任何在pub.dev上发布的包名,PubTrace就会为你展示以下信息:

累计下载量图表。这是一张覆盖52周时间的折线图,能够清晰地显示某个包的总下载量是如何随时间变化的。这与仅显示30天数据或每周数据的柱状图完全不同,这种实时累计的数据图能真实反映一个包的实际发展轨迹。

最准确的数据。所有关于总下载量、获得点赞数、获得的pub积分以及发布者信息等数据,都是直接从pub.dev的API中获取的,因此这些数据是最新且最准确的。

数据更新时间。PubTrace会明确显示数据最后一次被获取的时间。它并不声称自己提供实时数据,但确实能确保数据在一小时以内是最新的。

验证功能。每个页面都设有验证板块,其中会显示用于获取数据的具体curl命令。你可以复制这些命令,在自己的终端中运行它们,从而亲自验证所有数据的准确性。这一功能是PubTrace最核心的特点之一——它意味着你完全不必信任PubTrace,你可以随时自行对其进行验证。

以下是在PubTrace中查询“dart_exceptor”时所得到的数据与pub.dev上显示的数据之间的对比:

pub.dev显示的下载量为174次(统计周期为30天);而PubTrace显示的是8周内的累计下载次数,并且还提供了图表,详细展示了这些下载数据的具体获取时间以及数量的变化趋势。

这两个数字实际上都来源于同一份pub.dev的数据。只不过PubTrace呈现出了更全面的信息而已。

任何开发者都可以使用该工具,无需注册账户。请访问https://pubtrace.dev亲自尝试一下吧。

关于不使用数据库的架构决策

在PubTrace的开发过程中,最重要的架构决策就是决定不存储任何数据。

你在PubTrace上看到的每一个数字,都是在你请求查看某个包的信息时,实时从pub.dev的API中获取到的。该系统没有下载历史的数据库,也没有任何历史记录。所有的图表都是根据pub.dev当前的数据,在服务器端实时计算得出的。

做出这样的选择是有原因的——那就是为了保持透明度与真实性。

如果PubTrace自己存储了历史数据,那么你就必须相信这些数据的准确性。你必须相信我能够准确收集这些数据,确保在数据收集期间系统没有出现故障,同时也必须相信我的存储系统没有出现问题。换句话说,你其实是在信任一个中间环节。

但由于采用了不使用数据库的架构,你根本不需要信任PubTrace。PubTrace展示给你的每一个数字都可以通过curl命令重新计算得出。PubTrace实际上只是基于pub.dev的数据进行进一步处理的一个工具而已,并不是真实数据的来源。

1小时的缓存机制

如果每次请求都直接从pub.dev获取数据,那么不仅会浪费资源,也会对pub.dev的服务器造成负担。因此,PubTrace会为响应结果设置1小时的缓存时间。这意味着:

如果你在下午3点查询“dart_exceptor”,PubTrace会先从pub.dev获取数据并将其缓存起来;如果有人在下午3:30再次查询同一个包的信息,他们就会得到缓存的结果。到了下午4点,缓存失效后,系统会重新从pub.dev获取最新数据。

这个缓存机制是明确告知用户的,你也可以看到数据是什么时候被最后一次获取的。我们需要强调的是,这些数据并不是实时更新的,只是在1小时内的最新数据而已。

验证面板

PubTrace上的每个包页面都配备了验证面板。该面板会显示用于获取该包数据的具体curl命令。任何开发者都可以复制这些命令,在自己的终端中运行它们,从而验证PubTrace展示的所有数据是否准确。

这不仅仅是一个方便的功能,更是PubTrace的核心价值所在。使用PubTrace的意义就在于——你根本不需要信任它。

PubTrace是如何计算这些数据的

了解数据背后的计算过程有助于让你更加信任其展示的结果。

累计图表

67fe11eb-6bb9-4119-83a6-431ff844d170

PubTrace会从指标数据端点获取过去52周的下载数据,并计算出这些数据的累计值。第52周被视为起始点,之后的每一周都会将其下载量加到累计总数中。最终得到的累积增长图表能够真实反映某个软件包的下载趋势。

这与pub.dev显示的数据有本质区别:pub.dev展示的是每周下载量的柱状图,因此那些每周下载量稳定的软件包在图表上看起来变化不大;而PubTrace展示的是累计下载量的折线图,这样就能清楚地看到同一个软件包的下载量是如何逐周稳步增长的。

实际上,两者显示的数据是相同的。只是呈现方式不同而已,而累积视图能更全面地反映实际情况。

新发布软件包的规则

如果一个软件包是在52周之前发布的,PubTrace会在图表上标注实际可用的数据周期长度。例如,一个在8周前发布的软件包,其图表会明确显示8周内的下载数据。PubTrace不会对缺失的数据进行推测或估算,它只会展示实际存在的数据而已。

数据截断的规则

指标数据端点只存储过去52周的数据。对于发布时间超过1年的软件包,该端点无法提供52周之前的数据。PubTrace会明确说明这一点——其图表仅显示52周内的数据,并不会声称能展示旧软件包从发布第一天的起就开始的下载情况。

而对于发布时间不足52周的软件包,其图表会显示自发布以来的所有下载数据,从而呈现其完整的成长历程。

数据的准确性验证

PubTrace进行的每一项计算都可以通过原始API响应数据进行核实。某个软件包的累计下载量其实就是totalWeeklyDownloads中这52个数据值的总和。你可以自己运行curl命令,对这些数据求和,如果得到的结果与PubTrace显示的结果相同,那就说明没有问题;如果不同,那就说明存在错误,我希望你能及时告知我。

这对工程师有什么帮助

对软件包开发者而言

最直接的好处就是能够清楚地了解自己开发的软件包的实际发展情况。目前pub.dev上显示的数字并不能真实反映软件包的成长历程,那只是过去30天的数据快照。而PubTrace能展示完整的52周数据,让你清楚地知道自己的软件包是在增长、保持稳定还是在下降,从而根据真实的数据做出决策。

对个人作品集和证明材料而言

在Dart和Flutter社区中,许多工程师都在努力构建自己的作品集,并申请那些需要证明自己具备社区贡献能力或技术影响力的高级职位。在pub.dev上显示的55次下载量并不能作为有力的证明;而一张能显示在8周内累计下载量达到174次的图表,再加上可验证的数据来源,就能呈现出完全不同的情况。

PubTrace能为你提供完整的数据信息,同时还能为你提供验证这些数据的工具。专门设置的验证功能就是为了确保这些数字是可以被独立核实的。没有必要相信别人,数据本身就能说明问题,而且这些数据也可以通过pub.dev自己的API进行验证。

为社区服务

任何开发者都可以通过PubTrace查询pub.dev上发布的所有公共包。你可以将这些包进行对比分析,了解某个包在发布后的第一年内发展情况如何。这样,在决定依赖哪些包时,你就能做出更加明智的选择——而这些判断不仅仅基于pub.dev提供的最近30天的数据,而是基于该包在整个发展过程中的完整轨迹。

为提升Dart和Flutter生态系统的透明度

Dart和Flutter生态系统正在不断发展,每周都有新的包被发布。不过,目前用来了解这一发展情况的工具仅限于pub.dev提供的最近30天的数据以及每周发布的柱状图。PubTrace则为人们提供了这些历史数据,使这些信息得以被直观地展示出来。

所有计算结果都是基于pub.dev自己的公共API得出的。没有任何数据是人为编造的,也没有任何数值是超出API提供范围进行估算的。我们的目标就是提供真实、可靠的数据,让每一位工程师都能对其进行验证。

结论

pub.dev提供的最近30天的下载量数据确实能反映一些情况,但并不能说明全部问题。对于那些希望了解自己包的发展情况的开发者来说,这个时间范围显然不够用;而对于整个社区而言,在选择依赖哪些包时,这样的数据也同样无法提供足够的参考依据。

其实,我们能够获得更全面的数据。pub.dev通过其指标接口提供了每周的下载量历史记录;官方API则提供了元数据、发布者信息以及相关评分。PubTrace将这些数据结合起来进行综合分析,最终以一种真实、可验证且实用的方式呈现出来。

不需要任何数据库,也不需要任何估算值,更无需信任什么第三方数据。所有的数值都可以通过直接调用pub.dev的API来获取。

如果你在pub.dev上发布了自己的包,那么你实际获得的下载量数据很可能比pub.dev显示的要高。去亲自查看一下真实的数据吧。

请访问https://pubtrace.dev,输入你感兴趣的包名进行查询。查看验证结果,自己运行相关的curl命令,然后将链接分享给你的团队。

这些数据其实一直都存在,只是之前没有以直观的方式呈现出来而已。

相关文章

技术实践

TimescaleDB课程——用于处理时间序列数据的PostgreSQL

对于现代开发者而言,高效地管理庞大且快速增长的数据集是一项至关重要的能力。无论你是负责跟踪API请求日志、监控物联网设备的遥测数据,还是为人工智能应用构建仪表盘,如果不对时间序列数据进行优化处理,那么这些操作很快就会导致标准的PostgreSQL查询速度变得极慢。我们刚刚在freeCodeCamp.org的YouTube频道上发布了一门新课程,这门课程将帮助你全面了解TimescaleDB。 通过这门课程,你将获得实际使用TimescaleDB的经验,学习如何将PostgreSQL升级为经过优化的时间序列数据库。你还将学会优化查询速度、大幅减少存储空间占用,并确保你的仪表盘在处理大量数据时仍能

阅读全文
技术实践

“Graphify”:通过统一代码库的上下文信息来简化智能软件工程的开发流程

Graphify是一款开源工具,其设计目的在于将代码库及非结构化数据转化为可供查询的知识图谱。该工具于2026年4月正式推出,有效解决了人工智能编码辅助工具在处理多文件数据时所面临的推理难题。最近的更新进一步提升了解析器的功能以及跨文件的数据处理能力。社区用户的反馈表明,这一技术架构具有很大的潜力,但同时也指出了其在日常工作中集成使用时所存在的挑战。 作者:Olimpiu Pop

阅读全文
技术实践

如何使用Python和依赖关系图来检测公共数据集中隐藏的目标泄露现象

不久前,我给一个机器学习模型提供了来自公共CDC数据集的五列数据,让它尝试预测同一文件中的第六列数据。该模型的R²值为0.998,这个数值已经非常接近完美了。 虽然这个结果看起来很成功,但实际上该模型对现实世界的认知几乎没有任何提升——因为CDC本身就是根据其他五列数据计算出了第六列数据的,所以该模型实际上只是机械地应用了CDC的计算方法而已。 数据科学家将这种问题称为 目标信息泄露 ,当输入给模型的数据本身就已经包含了答案的某些信息时,就会发生这种情况。 在公共数据中,这类问题很容易被隐藏起来,因为大量的公共数据都是通过其他公共数据计算得出的。例如,一个政府指数可能是根据调查数据构建的,而另

阅读全文
技术实践

如何将RECIST曲线转换为三维肿瘤分割掩膜

放射科医师可以通过在CT扫描图像中绘制一条直线来标记肿瘤的位置。而要完成完整的3D分割,就需要在肿瘤出现的所有切片中都标出其边界,这个过程耗时较长。 本教程介绍了Lumina的工作原理。该系统利用CT扫描图像以及RECIST标记线,生成被标记肿瘤的3D分割掩膜。 Lumina是专为 FLARE 2026泛癌症分割挑战赛 开发的。该系统设计用于在内存限制为8GB、推理时间上限为60秒的CPU上运行。 本教程涵盖了形成最终系统的各项关键设计决策、实现细节以及相关实验内容。 我们将涵盖以下内容: Lumina的功能 Lumina处理流程概述 先决条件 步骤1:编码前请先审核您的数据 扫描图像已经过亮

阅读全文