分析 PyPI 包下载量¶
本节介绍如何使用公共 PyPI 下载统计数据集,以了解有关 PyPI 上托管的一个或多个包的下载量。例如,您可以使用它来发现用于下载包的 Python 版本分布。
背景¶
PyPI 不显示下载统计数据,原因有多种:[1]
与内容分发网络 (CDN) 配合使用效率低下: 下载统计数据不断变化。将其包含在项目页面(这些页面被大量缓存)中,将需要更频繁地使缓存失效,并降低缓存的整体效率。
高度不准确: 许多因素会阻止下载计数准确,其中包括:
pip的下载缓存(降低下载计数)内部或非官方镜像(可以提高或降低下载计数)
未托管在 PyPI 上的包(用于比较)
非官方脚本或试图夸大下载计数(提高下载计数)
已知历史数据质量问题(降低下载计数)
不是特别有用: 一个项目被下载了很多次并不意味着它很好;同样,一个项目没有被下载很多次并不意味着它很糟糕!
简而言之,由于其价值因各种原因而较低,并且使其工作所需的权衡成本较高,因此它一直未能有效利用有限的资源。
公共数据集¶
作为替代方案,Linehaul 项目 将 PyPI 的下载日志流式传输到 Google BigQuery [2],在那里它们被存储为公共数据集。
设置¶
为了使用 Google BigQuery 查询 公共 PyPI 下载统计数据集,您需要一个 Google 帐户,并在 Google Cloud Platform 项目上启用 BigQuery API。您可以使用 BigQuery 免费套餐每月运行多达 1TB 的查询,无需信用卡。
导航到 BigQuery Web UI。
创建一个新项目。
启用 BigQuery API。
有关如何开始使用 BigQuery 的更详细说明,请查看 BigQuery 快速入门指南。
数据模式¶
Linehaul 为每个下载在 bigquery-public-data.pypi.file_downloads 表中写入一个条目。该表包含有关下载了哪个文件以及如何下载的信息。来自 表模式 的一些有用列包括:
列 |
Description |
示例 |
|---|---|---|
时间戳 |
日期和时间 |
|
file.project |
项目名称 |
|
file.version |
包版本 |
|
details.installer.name |
安装程序 |
pip, bandersnatch |
details.python |
Python 版本 |
|
有用查询¶
通过点击“编写查询”按钮在 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()
下载次数 |
|---|
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()
下载次数 |
|---|
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
下载次数 |
月 |
|---|---|
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 |
下载次数 |
|---|---|
3.7 |
18051328726 |
3.6 |
9635067203 |
3.8 |
7781904681 |
2.7 |
6381252241 |
null |
2026630299 |
3.5 |
1894153540 |
获取工件的绝对链接¶
有时,根据哈希值获取从 PyPI 下载工件的绝对链接会很有用,例如,如果某个特定项目或发布已从 PyPI 中删除。元数据表包含 path 列,其中包含哈希值和工件文件名。
注意
此处生成的 URL 不保证是稳定的,但目前与 PyPI 工件托管的 URL 一致。
SELECT
CONCAT('https://files.pythonhosted.org/packages', path) as url
FROM
`bigquery-public-data.pypi.distribution_metadata`
WHERE
filename LIKE 'sampleproject%'
url |
|---|
注意事项¶
除了上述背景中列出的注意事项外,Linehaul 曾存在一个 bug,导致其在 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¶
pypinfo 是一个命令行工具,提供对数据集的访问并可以生成几个有用的查询。例如,您可以使用命令 pypinfo package_name 查询包的总下载量。
使用 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 访问查询结果。