APIレート制限を超えてGitHubデータをスクレイピング: スター、依存関係

GitHubのAPIは、認証されていない呼び出しを1時間に60回に制限し、依存関係とトレンドを完全に隠します。ここでは、重要なシグナルを安価なIPでどのように抽出するかを説明します。

GitHubは研究の宝庫です - 採用曲線、競合の勢い、依存関係グラフ、採用シグナル - そしてその公式APIはその一部を無料で提供します。しかし、それはそこまでです。認証されていない呼び出しは1時間に60回に制限されており、人々が最も求める2つのデータセット、依存関係グラフとトレンドページはAPIには全く含まれていません。このガイドでは、これらの制限を超えてGitHubデータをスクレイピングする方法を説明します: APIが提供するもの、HTMLから読み取る必要があるもの、そしてGitHubが安価なデータセンターとIPv6プロキシが適切なツールである稀なターゲットである理由。

限界を知ってから挑戦する

APIから始めましょう - それは構造化されており、認証すればクォータが安価です。すべてを形作る数字: 認証されていないRESTリクエストは1時間に60回に制限されており、IPごとにカウントされます; 認証トークンは1時間に5,000回に増えます; Search APIはさらに厳しく、認証された場合は1分間に30回、認証されていない場合は10回です。重要な詳細は、認証されていない上限がIPごとにカウントされることです - これが、複数のIPに読み取りをルーティングすることでヘッドルームを増やす理由です。

import requests

# Authenticated API call - watch the rate-limit headers
headers = {"Authorization": "Bearer YOUR_GH_TOKEN",
           "Accept": "application/vnd.github+json"}
r = requests.get("https://api.github.com/repos/psf/requests", headers=headers, timeout=15)
repo = r.json()
print(repo["stargazers_count"], repo["forks_count"], repo["open_issues_count"])
print("remaining this hour:", r.headers["X-RateLimit-Remaining"])

APIがクリーンに公開しているものにはAPIを使用し、ファイル内容にはgit cloneを使用します - リポジトリをローカルでクローンして処理する方が、個々のファイルページをスクレイピングするよりも速くて優しいです。HTMLをスクレイピングするのは、APIがレート制限して無意味にしたり、完全に省略したりするシグナルのためです。

HTMLから読み取る必要があるもの

3つの高価値データセットはレンダリングされたページにのみ存在します。依存関係グラフ - GitHubの「使用している」カウントとパッケージに依存するリポジトリのリスト - は最も強力な採用指標の1つであり、APIには含まれていません。トレンドページ(github.com/trending、言語と期間でフィルタリング可能)はHTMLのみです。そしてトピックページは、検索クォータが許すよりもはるかに有用にリポジトリをテーマごとに表示します。これら3つはすべてサーバーレンダリングされたプレーンHTMLなので、シンプルなリクエストと解析で動作します - ブラウザは必要ありません。

import requests
from bs4 import BeautifulSoup

# Scrape the trending page through a datacenter proxy
PROXY = "http://USER:PASS@dc.quantumproxies.io:8000"

def trending(language="python", since="daily"):
    url = f"https://github.com/trending/{language}?since={since}"
    r = requests.get(url, proxies={"https": PROXY}, timeout=20,
                     headers={"User-Agent": "Mozilla/5.0"})
    soup = BeautifulSoup(r.text, "html.parser")
    repos = []
    for row in soup.select("article.Box-row"):
        name = row.select_one("h2 a")["href"].strip("/")
        stars = row.select_one("a[href$='/stargazers']")
        repos.append({"repo": name,
                      "stars": stars.get_text(strip=True) if stars else None})
    return repos

print(trending("rust", "weekly")[:5])
GitHub APIレート制限を示す統計パネル: 1時間に60回の認証されていないリクエスト、5,000回の認証されたリクエスト、1分間に30回の検索
認証されていない上限はIPごとにカウントされます - これが、読み取りをプール全体に広げることが効果的である理由です。

GitHubはデータセンター(おそらくIPv6)ターゲットです

ここが人々が過剰にエンジニアリングする部分です。GitHubの公開ページはサーバーレンダリングされており、寛容で、攻撃的なJavaScriptチャレンジを持たないため、読み取るために高級な住宅用IPは必要ありません。これはデータセンタープロキシの教科書的なケースです: 安価で速く、豊富で、広く分散されているため、単一のIPが認証されていない制限に近づいたり、二次レート制限を引き起こしたりすることはありません。ここで住宅用を選ぶのは、経済的なIPで完璧にできる仕事に贅沢な価格を払うことです。データセンタープロキシを使用するべき時に関するガイドでは、まさにこのような寛容で高スループットのターゲットについて詳しく説明しています。

さらに安価なオプションがテストする価値があります: IPv6です。ターゲットがIPv6で応答する場合、IPv6プロキシプールは、巨大で低コストのアドレス空間を提供します - IPごとに制限された読み取りを数千の出口に広げるのに理想的です。GitHubはIPv6サポートを展開しているため、これはチェックする価値のある数少ない大規模ターゲットの1つです。コミットする前にテストしてください: ターゲットを無料のIPv6互換性チェッカーで実行し、完全なIPv6プロキシガイドで経済性を確認してください。

GitHub用の高速データセンタープロキシを入手

二次レート制限に注意

1時間ごとの上限は、遭遇する唯一の制限ではありません。GitHubは、バースト的、高度に同時発生的、または疑わしく規則的なトラフィックに反応する不正検出も実行しています - そのため、数値制限の下で快適に座っていても、単一のIPからのハンマーリングは一時的なブロックを受ける可能性があります。防御策は、あなたを礼儀正しいクライアントにするのと同じものです: 同時実行数を制限し、リクエスト間に少しのジッターを追加し、サーバーが提供するRetry-Afterヘッダーを尊重し、負荷を広げて単一の出口が暴走パターンを持たないようにします。これが広いプールが重要である本当の理由です - それは単に1時間60回の算術ではなく、個々のIPがスクリプトの暴走のように見えるべきではないということです。最初の403またはスローダウンでバックオフし、より長い禁止に直面する代わりに直ちに再試行しないでください。

リポジトリデータを開発ツールのインテリジェンスに変える

これらすべての目的は分析レイヤーです。競合ライブラリのスターの速度と依存関係のカウントを時間と共に追跡することで、リアルタイムでの採用を観察できます。言語ごとにトレンドページを週ごとに比較して、明らかになる前に上昇するツールを見つけます。貢献者リストを引き出して、チームの規模と採用シグナルを読み取ります。トピック全体で言語の内訳を組み合わせて、エコシステム全体をマッピングします。リポジトリをスケジュールに従ってスナップショットし、各キャプチャをタイムスタンプ付きで保存し、デルタが製品になります - 単一の数字ではなく、勢いです。40,000のスターの一度の読み取りは雑学ですが、同じリポジトリが週に2,000のスターを追加し、依存関係のカウントが上昇している場合、それは市場が気づく前に行動できる本当の採用シグナルです。

import requests
from bs4 import BeautifulSoup

# The 'Used by' dependents count - a top adoption signal, HTML-only
def used_by(owner, repo):
    url = f"https://github.com/{owner}/{repo}/network/dependents"
    proxy = "http://USER:PASS@dc.quantumproxies.io:8000"
    r = requests.get(url, proxies={"https": proxy}, timeout=20,
                     headers={"User-Agent": "Mozilla/5.0"})
    soup = BeautifulSoup(r.text, "html.parser")
    tab = soup.select_one("a.btn-link.selected")
    return tab.get_text(strip=True) if tab else None

print(used_by("pallets", "flask"))   # e.g. '1.4m Repositories'

ボリュームでコストを抑える1つの習慣: 必要なものだけをリクエストすること。リポジトリページは軽量ですが、数千のリポジトリにファンアウトする場合、アセットをブロックし、接続を再利用します - プロキシ帯域幅を削減するためのノートは、安価なターゲットにも適用されます。

GitHubをスクレイピングするためのデータセンター、IPv6、住宅用プロキシの比較
寛容な公開ターゲットの場合、データセンターとIPv6 IPはコストで勝ちます; 住宅用はより厳しいサイトに保存します。

よくある質問

GitHubのAPIレート制限は何ですか?

認証されていないRESTリクエストは1時間に60回に制限されており、IPアドレスごとにカウントされます。認証トークンはそれを1時間に5,000回に引き上げます。Search APIは別で、さらに厳しく、認証された場合は1分間に30回、認証されていない場合は10回です。認証されていない制限がIPごとであるため、プロキシプールに読み取りを広げることは、収集を拡大する効果的な方法です。

APIが公開していないGitHubデータをスクレイピングできますか?

はい。依存関係グラフ(「使用している」)、トレンドページ、トピックリスト、スターゲイザータイムラインは、HTMLのみまたはAPIを介して厳しくクォータ制限されています。それらはプレーンサーバーレンダリングされたページなので、BeautifulSoupを使用したリクエストと解析でブラウザなしで動作します。データセンタープロキシを通じてルートし、読み取りを広げて二次レート制限を超えないようにします。

GitHubに住宅用プロキシが必要ですか?

通常は必要ありません。GitHubの公開ページは寛容でサーバーレンダリングされており、攻撃的なJavaScriptチャレンジがないため、安価なデータセンタープロキシで十分です - 目標はIPにリクエストを広げることであり、それを家庭として偽装することではありません。ターゲットがIPv6で応答する場合、IPv6プールはさらに安価です。本当に敵対的なターゲットには住宅用IPを予約してください。

git cloneを使用するべきか、ファイルページをスクレイピングするべきか?

ファイル内容にはクローンを使用します。git cloneを実行してリポジトリをローカルで処理する方が速く、GitHubに優しく、ファイルごとのレート制限を完全に回避します。HTMLスクレイピングとAPIは、チェックアウトされたファイル自体から取得できないメタデータとシグナル - スター、依存関係、トレンド、貢献者 - のために予約してください。

GitHubは層状のアプローチを報います: APIが寛大なところではAPIを使用し、ファイルにはgit cloneを使用し、採用シグナルを隠すHTMLスクレイピングを行います - すべてを安価なIPに広げて、単一のアドレスが1時間60回の壁にぶつからないようにします。IPv6をテストし、データセンタープールに頼り、プラットフォーム全体がライブの開発エコシステムデータセットになります。

高ボリュームのGitHub読み取りにIPv6プロキシを試してみてください