如何取得 PyPI 上所有註冊的套件

Neil - May 31 - - Dev Community

根據 PEP 503 (Simple Repository API) 文件裡的說明,我們可以透過 https://pypi.org/simple/ 這支 API 來取得所有登記在 PyPI 之下的 Python 套件。當我們向這個 API 發出請求後, 便可得到類似下面的回應:

<!DOCTYPE html>
<html>
  <body>
    <a href="/frob/">frob</a>
    <a href="/spamspamspam/">spamspamspam</a>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

這是一個 HTML 網頁的寫法,其中 href 之後的文字,例如 /frob/ 或 /spamspamspam/,顯示了該套件的詳細資訊所在的位置,中間的字串是該套件的標準化名稱;而在角括弧中間的文字,例如 frob 或 spamspamspam,則是套件的原始名稱。

因此我們就可以寫一支簡單的 shell script 來取得這份 HTML 的內容:

$ curl -s https://pypi.org/simple/
<!DOCTYPE html>
<html>
  <head>
    <meta name="pypi:repository-version" content="1.1">
    <title>Simple index</title>
  </head>
  <body>
<a href="/simple/0/">0</a>
<a href="/simple/0-0/">0-._.-._.-._.-._.-._.-._.-0</a>
<a href="/simple/000/">000</a>
…
Enter fullscreen mode Exit fullscreen mode

為了更有效地篩選資訊,我們增加過濾條件,只保留含有 href 的項目:

$ curl -s https://pypi.org/simple/ | grep -Eo 'href="[^"]+"'
href="/simple/0/"
href="/simple/0-0/"
href="/simple/000/"
href="/simple/00000/"
href="/simple/0000000/"
href="/simple/00000000/"
href="/simple/000000000000000000000000000000000000000000000000000000000/"
href="/simple/00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000/"
href="/simple/0-0-1/"
href="/simple/00101s/"
…
Enter fullscreen mode Exit fullscreen mode

接著,我們移除 href、simple 以及其他符號,只留下標準化名稱:

$ curl -s https://pypi.org/simple/ | grep -Eo 'href="[^"]+"' | awk -F '/' '{print $3}'
0
0-0
000
00000
0000000
00000000
000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0-0-1
00101s
Enter fullscreen mode Exit fullscreen mode

這樣我們便能取得所有在 PyPI 上登記的套件。

為了確認我們拿到的列表準確無誤,再進行一道處理程序:

$ curl -s https://pypi.org/simple/ | grep -Eo 'href="[^"]+"' | awk -F '/' '{print $3}' | wc -l
  534413
Enter fullscreen mode Exit fullscreen mode

這數字與 PyPI 官網上的非常接近,大工告成!

. . . . . . . . . . . . . . . . . . . . . . . . . . .