分析 PyPI 软件包下载量#

本部分介绍如何使用公共 PyPI 下载统计数据集来详细了解托管在 PyPI 上的软件包(或软件包)的下载量。例如,你可以使用它来发现用于下载软件包的 Python 版本分布。

背景#

出于多种原因,PyPI 不会显示下载统计数据:[1]

  • 与内容分发网络 (CDN) 配合使用效率低下:下载统计数据会不断变化。将它们包含在大量缓存的项目页面中,将需要更频繁地使缓存失效,并降低缓存的整体有效性。

  • 极不准确:许多因素会阻止下载计数准确,其中包括

    • pip 的下载缓存(降低下载计数)

    • 内部或非官方镜像(既可以提高也可以降低下载计数)

    • 未托管在 PyPI 上的软件包(为了比较)

    • 非官方脚本或尝试增加下载计数(提高下载计数)

    • 已知的历史数据质量问题(降低下载计数)

  • 并非特别有用:仅仅因为一个项目被下载了很多次并不意味着它很好;同样,仅仅因为一个项目没有被下载很多次并不意味着它很糟糕!

简而言之,由于其价值出于各种原因较低,并且使其发挥作用所需的权衡很高,因此它并不是有效利用有限资源的方式。

公共数据集#

作为替代方案,Linehaul 项目将 PyPI 的下载日志流式传输到 Google BigQuery [2],它们存储为公共数据集。

开始设置#

为了使用 Google BigQuery 查询 公共 PyPI 下载统计数据集,你需要一个 Google 帐户,并在 Google Cloud Platform 项目中启用 BigQuery API。你可以每月运行高达 1TB 的查询 使用 BigQuery 免费层,无需信用卡

有关如何开始使用 BigQuery 的更详细说明,请查看 BigQuery 快速入门指南

数据架构#

Linehaul 会为每次下载在 bigquery-public-data.pypi.file_downloads 表中写入一个条目。该表包含有关下载了哪些文件以及如何下载文件的信息。表架构 中一些有用的列包括

说明

示例

timestamp

日期和时间

2020-03-09 00:33:03 UTC

file.project

项目名称

pipenv, nose

file.version

软件包版本

0.1.6, 1.4.2

details.installer.name

安装程序

pip, bandersnatch

details.python

Python 版本

2.7.12, 3.6.4

有用的查询#

通过单击“撰写查询”按钮在 BigQuery Web UI 中运行查询。

请注意,这些行存储在分区表中,这有助于限制查询的成本。这些示例查询通过筛选 timestamp 列来分析近期历史记录中的下载情况。

统计软件包下载量#

以下查询统计项目“pytest”的总下载量。

#standardSQL
SELECT COUNT(*) AS num_downloads
FROM `bigquery-public-data.pypi.file_downloads`
WHERE file.project = 'pytest'
  -- Only query the last 30 days of history
  AND DATE(timestamp)
    BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
    AND CURRENT_DATE()

num_downloads

26190085

要仅统计来自 pip 的下载量,请筛选 details.installer.name 列。

#standardSQL
SELECT COUNT(*) AS num_downloads
FROM `bigquery-public-data.pypi.file_downloads`
WHERE file.project = 'pytest'
  AND details.installer.name = 'pip'
  -- Only query the last 30 days of history
  AND DATE(timestamp)
    BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
    AND CURRENT_DATE()

num_downloads

24334215

按时间推移统计软件包下载量#

要按月度下载量分组,请使用 TIMESTAMP_TRUNC 函数。按此列筛选还可以降低相应的成本。

#standardSQL
SELECT
  COUNT(*) AS num_downloads,
  DATE_TRUNC(DATE(timestamp), MONTH) AS `month`
FROM `bigquery-public-data.pypi.file_downloads`
WHERE
  file.project = 'pytest'
  -- Only query the last 6 months of history
  AND DATE(timestamp)
    BETWEEN DATE_TRUNC(DATE_SUB(CURRENT_DATE(), INTERVAL 6 MONTH), MONTH)
    AND CURRENT_DATE()
GROUP BY `month`
ORDER BY `month` DESC

num_downloads

month

1956741

2018-01-01

2344692

2017-12-01

1730398

2017-11-01

2047310

2017-10-01

1744443

2017-09-01

1916952

2017-08-01

按时间推移统计 Python 版本#

details.python 列中提取 Python 版本。警告:此查询处理超过 500 GB 的数据。

#standardSQL
SELECT
  REGEXP_EXTRACT(details.python, r"[0-9]+\.[0-9]+") AS python_version,
  COUNT(*) AS num_downloads,
FROM `bigquery-public-data.pypi.file_downloads`
WHERE
  -- Only query the last 6 months of history
  DATE(timestamp)
    BETWEEN DATE_TRUNC(DATE_SUB(CURRENT_DATE(), INTERVAL 6 MONTH), MONTH)
    AND CURRENT_DATE()
GROUP BY `python_version`
ORDER BY `num_downloads` DESC

python

num_downloads

3.7

18051328726

3.6

9635067203

3.8

7781904681

2.7

6381252241

null

2026630299

3.5

1894153540

注意事项#

除了上面背景中列出的注意事项之外,Linehaul 还存在一个错误,导致其在 2018 年 7 月 26 日之前严重低估了下载统计信息。此日期之前的下载在比例上是准确的(例如,Python 2 与 Python 3 下载的百分比),但总数比实际值低一个数量级。

其他工具#

除了使用 BigQuery 控制台之外,在分析下载统计信息时还有一些其他工具可能很有用。

google-cloud-bigquery#

您还可以通过 BigQuery API 和 google-cloud-bigquery 项目(BigQuery 的官方 Python 客户端库)以编程方式访问公共 PyPI 下载统计信息数据集。

from google.cloud import bigquery

# Note: depending on where this code is being run, you may require
# additional authentication. See:
# https://cloud.google.com/bigquery/docs/authentication/
client = bigquery.Client()

query_job = client.query("""
SELECT COUNT(*) AS num_downloads
FROM `bigquery-public-data.pypi.file_downloads`
WHERE file.project = 'pytest'
  -- Only query the last 30 days of history
  AND DATE(timestamp)
    BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
    AND CURRENT_DATE()""")

results = query_job.result()  # Waits for job to complete.
for row in results:
    print("{} downloads".format(row.num_downloads))

pypinfo#

使用 pip 安装 pypinfo

python3 -m pip install pypinfo

用法

$ pypinfo requests
Served from cache: False
Data processed: 6.87 GiB
Data billed: 6.87 GiB
Estimated cost: $0.04

| download_count |
| -------------- |
|      9,316,415 |

pandas-gbq#

pandas-gbq 项目允许通过 Pandas 访问查询结果。

参考#