PythonでHacker Newsをスクレイピングする方法【2つの手法・完全コード付き】

最終更新日 April 16, 2026

数か月前、Thunderbit のチーム向けに Hacker News の注目記事を毎日まとめたダイジェストを作りたいと思いました。最初はサイトをブックマークして、毎朝ざっと目を通せばいいだろうと考えていたのですが、3日ほどで、見出しを読んでリンクをスプレッドシートにコピペするだけで、1日20分も食っていることに気づいたんです。

Hacker News は、ネット上でも屈指の濃いテック情報が集まる場所です。月間訪問数は約 件、毎日およそ1,300件の新規投稿、そして1万3,000件前後のコメントが生まれています。最新の技術トレンドを追いたい、ブランドの言及を監視したい、「Who’s Hiring」スレッドから採用パイプラインを作りたい、あるいは開発者コミュニティが何に関心を持っているのかを把握したい——そんなとき、手作業で追いかけるのはかなり骨が折れます。

朗報です。Python を使った Hacker News のスクレイピングは、驚くほどシンプルです。このガイドでは、BeautifulSoup を使った HTML スクレイピングと、公式の HN Firebase API という2つの実践的な方法を、ページネーション、データ出力、本番運用を見据えた設計、そして Python を使うほどでもない場面向けのノーコード手段まで含めて、まるっと解説します。

なぜ Python で Hacker News をスクレイピングするのか?

Hacker News は、ただのリンク集ではありません。コミュニティ主導で厳選されたフィードで、投票と活発な議論によって面白いテック記事が自然と上に上がってきます。利用者はテクノロジー関連の職種に大きく偏っており(約 )、さらに直接流入が66%を占めることから、たまたま流れてくる閲覧者ではなく、習慣的に訪れる熱心な読者が多いことがわかります。

HN のデータを取る理由はたくさんあります。

ユースケース得られるもの
毎日のテックダイジェスト上位記事、スコア、リンクをメールや Slack で配信
ブランド/競合モニタリング自社や製品名が言及されたときにアラート
トレンド分析注目される技術、言語、トピックの推移を追跡
採用「Who’s Hiring」スレッドから求人、技術スタック、給与の手がかりを抽出
コンテンツ調査記事や投稿ネタとして伸びやすいテーマを発見
感情分析製品、リリース、業界動向に対するコミュニティの反応を把握

Stripe、Dropbox、Airbnb といった、合計で4,000億ドル超の企業も、Hacker News から初期の重要なフィードバックやユーザーを得たと語っています。Dropbox の Drew Houston は2007年4月に HN にデモを投稿し、1位を獲得、ベータ待機リストは一晩で5,000人から7万5,000人に急増しました。HN のデータは「面白い」だけでなく、ビジネス上の価値もかなり大きいのです。

データ自体は公開されていますが、サイト構造のせいで手作業の収集は面倒です。そこで、Python による自動化が現実的な解決策になります。

Python で Hacker News をスクレイピングする2つの方法

このガイドでは、すぐに動かせる完全な2つのアプローチを紹介します。

  1. requests + BeautifulSoup を使った HTML スクレイピング — news.ycombinator.com の生の HTML を取得し、解析して記事データを抜き出します。スクレイピングの基礎を学ぶのに最適で、ページ上に表示されている情報をそのまま取り出せます。
  2. 公式 Hacker News Firebase API — JSON エンドポイントを直接叩く方法です。HTML の解析は不要で、より信頼性の高いデータパイプライン、コメント取得、過去データの活用に向いています。

どちらが合うか判断しやすいよう、比較表を用意しました。

比較項目HTML スクレイピング(requests + BS4)HN Firebase APIThunderbit(ノーコード)
セットアップの難易度中(HTML セレクタの解析が必要)低(JSON エンドポイント)なし(Chrome 拡張を2クリック)
データの鮮度リアルタイムのトップページリアルタイム(ID 指定で任意アイテム取得)リアルタイム
レート制限リスク中(robots.txt で30秒のクロール間隔を要求)低(公式で比較的寛容)Thunderbit 側で管理
コメント取得難しい(入れ子の HTML)簡単(再帰的に item ID を辿る)サブページスクレイピング機能
過去データ限定的Algolia Search API 経由なし
向いている用途スクレイピングの基礎学習安定したデータパイプライン非エンジニア、素早いエクスポート

どちらの方法も、そのまま動かせる Python コード付きです。さらに、コードを書かずにデータだけ欲しい場合の方法も紹介します。

始める前に

  • 難易度: 初級〜中級
  • 所要時間: 各手法15〜20分程度
  • 必要なもの:
    • Python 3.11 以上
    • ターミナルまたはコードエディタ
    • Chrome ブラウザ(HN の HTML を確認したり、ノーコード手法を試したりする場合)
    • (任意、ノーコード手法用)

scrape-hacker-news-methods.webp

Python 環境の準備

HN のデータを触る前に、まずは環境を整えましょう。依存関係をきれいに保てるので、仮想環境を作るのがおすすめです。

1# 仮想環境を作成して有効化
2python3 -m venv hn-scraper
3# macOS/Linux:
4source hn-scraper/bin/activate
5# Windows:
6hn-scraper\Scripts\activate
7# 両方の方法で必要なパッケージをインストール
8pip install requests==2.33.1 beautifulsoup4==4.14.3 pandas==3.0.2 openpyxl==3.1.5

本番運用を見据えて、キャッシュやリトライも使うなら、次も入れておくと便利です。

1pip install requests-cache==1.3.1 tenacity==9.1.4

API キーも認証トークンも不要です。HN のデータは公開されています。

方法1: BeautifulSoup で Python スクレイピングする

まずは定番の方法です。HTML を取得し、解析して、欲しいデータを抜き出します。多くの人が最初に学ぶやり方で、HN のシンプルなテーブル構造は学習素材としてかなり優秀です。

ステップ1: Hacker News のトップページを取得する

エディタを開き、scrape_hn_bs4.py というファイルを作成してください。最初のコードは以下です。

1import requests
2from bs4 import BeautifulSoup
3> This paragraph contains content that cannot be parsed and has been skipped.
4print(f"Status: {response.status_code}, Page length: {len(response.text)} chars")

実行すると、Status: 200 と、40,000〜50,000文字ほどのページ長が表示されるはずです。これが HN トップページの生の HTML です。メモリ上に読み込まれ、解析できる状態になっています。

ステップ2: HTML 構造を理解する

HN は、現代的な CSS Grid や Flexbox ではなく、テーブルベースのレイアウトを採用しています。ページ上の各記事は、主に2つの <tr> 行で構成されています。

  • 記事行 (<tr class="athing submission">): ランク、タイトル、リンクを含む
  • メタデータ行(その次の <tr>): ポイント、投稿者、投稿時間、コメント数を含む

重要なセレクタは次のとおりです。

  • span.titleline > a — 記事タイトルと URL
  • span.score — 投票数(例: "118 points")
  • a.hnuser — 投稿者名
  • span.age — 投稿時間
  • .subtext 内の最後の <a> で、テキストに "comment" を含むもの — コメント数

Chrome で任意のタイトルを右クリックして「検証」を選ぶと、たとえば次のような HTML が見えます。

1<span class="titleline">
2  <a href="https://darkbloom.dev">DarkbloomPrivate inference on idle Macs</a>
3</span>

その下のメタデータ行は、こんな構造です。

1<span class="score" id="score_47788542">118 points</span>
2by <a href="user?id=twapi" class="hnuser">twapi</a>
3<span class="age" title="2026-04-16T04:06:39 1776312399">
4  <a href="item?id=47788542">2 hours ago</a>
5</span>
6| <a href="item?id=47788542">65&nbsp;comments</a>

このセレクタを理解することはかなり重要です。HN がマークアップを変更した場合は、ここを修正する必要があります。(ただし、後で紹介する API の方法なら、この問題を丸ごと避けられます。)

ステップ3: タイトル、リンク、スコアを抽出する

いよいよ本番です。各記事行を順番にたどり、記事行からタイトルとリンクを取得し、その直下のメタデータ行からスコアを取得します。

1import requests
2from bs4 import BeautifulSoup
3from pprint import pprint
4> This paragraph contains content that cannot be parsed and has been skipped.
5stories = []
6story_rows = soup.select("tr.athing")
7for row in story_rows:
8    # 記事行からタイトルと URL を取得
9    title_tag = row.select_one("span.titleline > a")
10    if not title_tag:
11        continue
12    title = title_tag.get_text()
13    link = title_tag.get("href", "")
14    # 次の行からメタデータを取得
15    meta_row = row.find_next_sibling("tr")
16    score = 0
17    author = ""
18    comments = 0
19> This paragraph contains content that cannot be parsed and has been skipped.
20> This paragraph contains content that cannot be parsed and has been skipped.
21# 50ポイント以上の投稿だけを抽出し、スコア順に並べ替え
22top_stories = sorted(
23    [s for s in stories if s["score"] >= 50],
24    key=lambda x: x["score"],
25    reverse=True,
26)
27pprint(top_stories[:10])

いくつか補足があります。

  • ウォルラス演算子 (:=) は Python 3.8 以上で使えます。span.score のように、行によって存在しない可能性がある要素を、その場で代入しながら確認できて便利です。たとえば求人投稿にはスコアがありません。
  • HN では「コメント」の前に \xa0(ノーブレークスペース)が入るので、それを区切りに数値を取り出しています。
  • 「Ask HN」など、HN 内の別ページに飛ぶ投稿は item?id= から始まる相対 URL になります。その場合は https://news.ycombinator.com/ を付け足すとよいでしょう。

ステップ4: 実行して結果を見る

保存して実行します。

1python scrape_hn_bs4.py

次のような出力が表示されるはずです。

1[{'author': 'twapi',
2  'comments': 65,
3  'score': 118,
4  'title': 'Darkbloom – Private inference on idle Macs',
5  'url': 'https://darkbloom.dev'},
6 {'author': 'sebg',
7  'comments': 203,
8  'score': 247,
9  'title': 'Show HN: I built an open-source Perplexity alternative',
10  'url': 'https://github.com/...'},
11 ...]

これで1ページ目の30件が取れました。ただし、HN には常に何百件ものアクティブな投稿があります。ページネーションについては後ほど解説します。

方法2: 公式 API を使って Hacker News をスクレイピングする

HN Firebase API は、Hacker News のデータを取るための正式な手段です。認証不要、API キー不要、HTML 解析も不要。クリーンな JSON が返ってきます。私は、本番で安定して動かしたい処理ではこの方法を使っています。

まず覚えておきたい API エンドポイント

ベース URL は https://hacker-news.firebaseio.com/v0/ です。必要なエンドポイントは次のとおりです。

This paragraph contains content that cannot be parsed and has been skipped.

記事アイテムは、たとえば次のような形式です。

1{
2  "by": "twapi",
3  "descendants": 65,
4  "id": 47788542,
5  "kids": [47789171, 47788769, 47788762],
6  "score": 118,
7  "time": 1776312399,
8  "title": "Darkbloom – Private inference on idle Macs",
9  "type": "story",
10  "url": "https://darkbloom.dev"
11}

kids フィールドには、直下のコメント ID が入っています。各コメントも1つの item であり、さらにその子コメントを持つことがあります。これがコメントツリーの構造です。

ステップ1: 上位記事 ID を取得する

scrape_hn_api.py というファイルを作成します。

1import requests
2import time
3from pprint import pprint
4API_BASE = "https://hacker-news.firebaseio.com/v0"
5# 上位記事 ID を取得
6response = requests.get(f"{API_BASE}/topstories.json")
7story_ids = response.json()
8print(f"Got {len(story_ids)} top story IDs")
9# Output: Got 500 top story IDs

1回のリクエストで500件の ID が取れます。解析もセレクタも不要、ただの JSON 配列です。

ステップ2: ID を使って記事詳細を取得する

次に、実際の記事データが必要です。ここで「大量取得」の課題が出てきます。500件の記事を取るなら、API 呼び出しも500回必要です。私の計測では、1件ずつ順番に取得すると1回あたり約1.2秒かかるため、500件ならおよそ10分になります。

多くの用途では、500件すべては必要ありません。以下は上位30件を取得するコードです。

1def fetch_story(story_id):
2    """HN API から1件の記事詳細を取得する"""
3    resp = requests.get(f"{API_BASE}/item/{story_id}.json")
4    return resp.json()
5> This paragraph contains content that cannot be parsed and has been skipped.
6# スコア順に並べて上位10件を表示
7top = sorted(stories, key=lambda x: x["score"], reverse=True)[:10]
8pprint(top)

time.sleep(0.1) は、相手への配慮として少し待つ処理です。Firebase API には明確なレート制限の記載はありませんが、どんな API でも休みなく叩き続けるのはよくありません。

ステップ3: コメントを取得する(再帰的にツリーをたどる)

ここで API の強みがはっきり出ます。HN のコメントは深く入れ子になっていて、返信の返信、そのまた返信…という構造です。HTML でやると、複雑な入れ子のテーブルを解析しなければなりません。一方 API なら、各コメントの kids に子コメントの ID が入っているので、再帰で木をたどるだけです。

1def fetch_comments(item_id, depth=0, max_depth=3):
2    """max_depth までコメントを再帰的に取得する"""
3    item = requests.get(f"{API_BASE}/item/{item_id}.json").json()
4    if not item or item.get("type") != "comment":
5        return []
6> This paragraph contains content that cannot be parsed and has been skipped.
7    if depth < max_depth and item.get("kids"):
8        for kid_id in item["kids"]:
9            comments.extend(fetch_comments(kid_id, depth + 1, max_depth))
10            time.sleep(0.05)
11    return comments
12# 例: 上位記事のコメントを取得
13if stories:
14    top_story = stories[0]
15    top_story_full = requests.get(f"{API_BASE}/item/{top_story['id']}.json").json()
16    if top_story_full.get("kids"):
17        print(f"\nComments for: {top_story['title']}")
18        all_comments = []
19        for kid_id in top_story_full["kids"][:5]:  # 先頭5件のトップレベルコメント
20            all_comments.extend(fetch_comments(kid_id, depth=0, max_depth=2))
21            time.sleep(0.1)
22        for c in all_comments[:15]:
23            indent = "  " * c["depth"]
24            preview = c["text"][:80].replace("\n", " ") if c["text"] else "[no text]"
25            print(f"{indent}[{c['author']}] {preview}...")

この再帰的なやり方は、入れ子の HTML コメントスレッドを解析するよりずっと楽です。コメントツリーを丸ごと取りたいなら、API 一択です。

ステップ4: 実行して結果を確認する

1python scrape_hn_api.py

整形された記事データのあとに、ネストされたコメントのプレビューが表示されます。データはよりクリーンで、コメントの取得も簡単、さらに HN 側が CSS クラス名を変えたせいでスクレイパーが壊れる心配もありません。

1ページ目の先へ: ページネーションと過去データ

多くの HN スクレイピング解説は、1ページ目の30件で終わります。デモとしては十分ですが、実務ではもっと深く取る必要があることが多いです。

BeautifulSoup で複数ページを取得する

HN のページネーションは、?p=2?p=3 のような単純な URL パターンです。各ページに30件が表示され、サイトはおおむね20ページ目あたりまで(合計約600件)を返します。それ以降は空ページになります。

1import time
2def scrape_hn_pages(num_pages=5):
3    """HN トップページを複数ページ分取得する"""
4    all_stories = []
5    for page in range(1, num_pages + 1):
6        url = f"https://news.ycombinator.com/news?p={page}"
7        response = requests.get(url, headers=headers)
8        soup = BeautifulSoup(response.text, "html.parser")
9        story_rows = soup.select("tr.athing")
10        if not story_rows:
11            print(f"Page {page}: no stories found, stopping.")
12            break
13        for row in story_rows:
14            title_tag = row.select_one("span.titleline > a")
15            if not title_tag:
16                continue
17            meta_row = row.find_next_sibling("tr")
18            score = 0
19            if meta_row and (score_tag := meta_row.select_one("span.score")):
20                score = int(score_tag.get_text().replace(" points", ""))
21> This paragraph contains content that cannot be parsed and has been skipped.
22        print(f"Page {page}: scraped {len(story_rows)} stories")
23        # robots.txt の30秒クロール間隔を尊重する
24        if page < num_pages:
25            time.sleep(30)
26    return all_stories
27stories = scrape_hn_pages(5)
28print(f"\nTotal stories scraped: {len(stories)}")

time.sleep(30) は重要です。HN の では、30秒のクロール間隔を明示的に求めています。無視すると、レート制限(HTTP 429)や一時的なブロックの対象になる可能性があります。5ページを30秒間隔で取ると約2分半かかりますが、ちゃんとルールを守った方法です。

ページネーションのコードを自分で管理したくないなら、 ならクリック式ページネーションや無限スクロールも自動対応できます。HN ページ下部の「More」ボタンも、設定なしで自動クリックします。

Algolia API で過去の Hacker News データを取得する

Firebase API で取れるのは現在のデータです。過去分析、たとえば「2023年の Python 関連の上位記事は何だったか?」とか「この5年で AI 関連の扱いはどう変わったか?」を知りたいなら、 が必要です。

1import requests
2ALGOLIA_BASE = "https://hn.algolia.com/api/v1"
3> This paragraph contains content that cannot be parsed and has been skipped.
4# 例: 2024年1月以降の、10ポイント以上の Python スクレイピング記事を探す
5results = search_hn(
6    query="python scraping",
7    tags="story",
8)
9print(f"Found {results['nbHits']} total results")
10for hit in results["hits"][:5]:
11    print(f"  [{hit.get('points', 0)} pts] {hit['title']}")

日付で絞り込みたい場合は、numericFilters を使います。

1import calendar, datetime
2# 2024年1月1日以降の記事
3start_date = datetime.datetime(2024, 1, 1)
4start_ts = int(calendar.timegm(start_date.timetuple()))
5> This paragraph contains content that cannot be parsed and has been skipped.
6Algolia API は高速で(サーバー側処理は5〜9ms程度)、API キーも不要、最大500ページまでページネーションに対応しています。大量の過去データ分析には、これが最適です。
7## スクレイピングした Hacker News データを CSV・Excel・Google Sheets に出力する
8私が見た HN スクレイピングのチュートリアルは、最後にターミナルへ `pprint()` で表示して終わるものが多いです。デバッグには便利ですが、日次ダイジェストを作ったりトレンド分析をしたりするなら、ファイルに出力する必要があります。そこで、やり方を紹介します。
9### Python で CSV に出力する
10```python
11import csv
12def export_to_csv(stories, filename="hn_stories.csv"):
13    """取得した記事を CSV に保存する"""
14    fieldnames = ["title", "url", "score", "author", "comments"]
15    with open(filename, "w", newline="", encoding="utf-8") as f:
16        writer = csv.DictWriter(f, fieldnames=fieldnames)
17        writer.writeheader()
18        writer.writerows(stories)
19    print(f"Saved {len(stories)} stories to {filename}")
20export_to_csv(stories)

Python で Excel に出力する

1import pandas as pd
2def export_to_excel(stories, filename="hn_stories.xlsx"):
3    """取得した記事を Excel に保存する"""
4    df = pd.DataFrame(stories)
5    df.to_excel(filename, index=False, engine="openpyxl")
6    print(f"Saved {len(stories)} stories to {filename}")
7export_to_excel(stories)

openpyxl がインストールされていることを確認してください。pandas は Excel 書き出しにこれを使います。入っていない場合は ImportError が出ます。

Google Sheets に直接送る(任意)

自動化フローを組むなら、gspread ライブラリを使って Google Sheets に直接送る方法もあります。これには、Google Cloud のサービスアカウント設定が一度だけ必要です。

1import gspread
2gc = gspread.service_account(filename="service_account.json")
3sh = gc.open("HN Daily Digest")
4worksheet = sh.sheet1
5# stories を行に変換
6header = list(stories[0].keys())
7rows = [list(s.values()) for s in stories]
8worksheet.clear()
9worksheet.update([header] + rows)
10print("Pushed to Google Sheets")

ノーコードでの出力代替案

サービスアカウントの設定や出力用コードを書くほうが、実際のスクレイピングより面倒に感じるなら、その感覚はよくわかります。Thunderbit では、スクレイピングしたデータを Excel、Google Sheets、Airtable、Notion にそのまま送れる無料エクスポート機能を用意しています。コードも認証情報も不要で、パイプラインの保守もいりません。一度きりのデータ取得なら、こちらのほうが確実に速いです。詳しくは後ほど紹介します。

スクレイパーを本番運用向けにする: エラーハンドリング、キャッシュ、スケジューリング

1回だけ遊びで動かすなら、ここまでのコードで十分です。でも、毎日のワークフローの一部として回すなら、追加でいくつか必要になります。

エラーハンドリングとリトライ

ネットワークは失敗します。サーバーは制限をかけます。1回の失敗で全体が止まるべきではありません。指数バックオフ付きのリトライ関数はこんな感じです。

1from tenacity import retry, stop_after_attempt, wait_exponential_jitter
2import requests
3@retry(stop=stop_after_attempt(5), wait=wait_exponential_jitter(initial=1, max=60))
4def fetch_with_retry(url):
5    """自動リトライと指数バックオフ付きで URL を取得する"""
6    response = requests.get(url, timeout=10)
7    response.raise_for_status()
8    return response
9# 使い方:
10try:
11    resp = fetch_with_retry("https://hacker-news.firebaseio.com/v0/topstories.json")
12    story_ids = resp.json()
13except Exception as e:
14    print(f"Failed after retries: {e}")

tenacity を使うと、リトライ処理をきれいに書けます。最大5回、ジッター付きの指数バックオフで再試行し、1秒から始めて最大60秒まで待機します。HTTP 429(レート制限)、503(サービス利用不可)、一時的なネットワークエラーをうまく吸収できます。

再クロールを避けるためにキャッシュする

開発中は、解析ロジックを調整しながら何度もスクレイパーを実行します。キャッシュがないと、毎回同じデータのために HN のサーバーへアクセスすることになります。requests-cache なら、たった2行で解決できます。

1import requests_cache
2requests_cache.install_cache("hn_cache", expire_after=3600)  # 1時間キャッシュ

この2行をスクリプトの先頭に入れると、すべての requests.get() がローカルの SQLite データベースに自動キャッシュされます。1時間以内に10回実行しても、実際にネットワークへ行くのは最初の1回だけです。これは で、それだけの価値があります。

クロールと解析を分ける

経験豊富なスクレイパーが重視する定番パターンは、「まず生データを保存し、あとから解析する」ことです。これなら、解析ロジックにバグがあっても、再取得せずに直して再解析できます。

1import os, json
2def crawl_and_save(story_ids, output_dir="raw_data"):
3    """記事データを取得して、生の JSON をディスクに保存する"""
4    os.makedirs(output_dir, exist_ok=True)
5    for sid in story_ids:
6        filepath = os.path.join(output_dir, f"{sid}.json")
7        if os.path.exists(filepath):
8            continue  # すでに取得済みの item はスキップ
9        resp = fetch_with_retry(f"{API_BASE}/item/{sid}.json")
10        with open(filepath, "w") as f:
11            json.dump(resp.json(), f)
12> This paragraph contains content that cannot be parsed and has been skipped.
13この2段階方式は、数百件のデータを扱いながら、処理の仕方を素早く改善したいときに特に役立ちます。
14### スクレイパーを定期実行する
15毎日の HN ダイジェストを作るなら、自動実行が必要です。代表的な方法は2つあります。
16**方法1: cron(Linux/Mac)**
17```bash
18# 毎日 UTC 8:30 に実行
1930 8 * * * /usr/bin/python3 /home/user/scrape_hn.py >> /home/user/scrape.log 2>&1

方法2: GitHub Actions(無料、サーバー不要)

1name: Scrape Hacker News
2on:
3  schedule:
4    - cron: '30 8 * * *'  # 毎日 UTC 8:30
5  workflow_dispatch:        # 手動実行ボタン
6jobs:
7  scrape:
8    runs-on: ubuntu-latest
9    steps:
10      - uses: actions/checkout@v4
11      - uses: actions/setup-python@v6
12        with:
13          python-version: '3.12'
14      - run: pip install requests beautifulsoup4 pandas openpyxl
15      - run: python scrape_hn.py
16      - run: |
17          git config user.name "GitHub Actions Bot"
18          git config user.email "actions@github.com"
19          git add -A
20          git diff --staged --quiet || git commit -m "Update HN data $(date -u +%Y-%m-%dT%H:%M:%SZ)"
21          git push

GitHub Actions のスケジュールにはいくつか注意点があります。cron の時刻はすべて UTC であること、15〜60分ほど遅れることが珍しくないこと(:00 ではなく :30 のような“きっちり時刻を避ける”設定が無難)、そして60日間アクティビティのないリポジトリではスケジュールワークフローが無効化される場合があることです。テスト用に手動実行できるよう、workflow_dispatch は必ず入れておきましょう。

もっと簡単にしたいなら、Thunderbit の Scheduled Scraper なら「毎朝8時にスクレイプ」のように自然な言葉で指定するだけで、サーバーも cron も不要です。

Python でやるには大げさなとき: Hacker News をノーコードでスクレイピングする

Python 好きとして、しかも開発者向けツールを作っている立場として正直に言います。もし必要なのが「今日の HN 上位100件を今すぐスプレッドシートに入れたい」だけなら、Python スクリプトを書いて、デバッグして、実行するのはオーバーヘッドが大きすぎます。仮想環境の作成、パッケージのインストール、セレクタの確認……その準備だけで、実際の収集より時間がかかることもあります。

そんなときにぴったりなのが です。流れはこんな感じです。

  1. Chrome で news.ycombinator.com を開く
  2. Thunderbit 拡張アイコンをクリックし、「AI Suggest Fields」を選ぶ
  3. AI がページを読み取り、Title、URL、Score、Author、Comment Count、Time Posted などの列を提案する
  4. 必要に応じて項目を調整する(名前の変更、削除、カスタム列の追加も可能。たとえば「AI/DevTools/Web/Other に分類する」といった AI プロンプトも追加できます)
  5. 「Scrape」をクリックすると、構造化されたテーブルでデータが表示される
  6. Excel、Google Sheets、Airtable、Notion に出力する

たった2クリックで構造化データが手に入ります。セレクタもコードも保守も不要です。

ここでの大きな利点は、Thunderbit の AI がレイアウト変更に自動対応することです。従来の CSS セレクタ型スクレイパーは、サイトのマークアップが変わると壊れがちです。HN の HTML は比較的安定していますが、実際に変更はありました(class="athing submission" が更新され、span.titleline が以前の a.storylink に取って代わりました)。AI ベースのスクレイパーは毎回ページを読み直すので、クラス名の変化を気にしなくて済みます。

python-vs-thunderbit-comparison.webp

Thunderbit はページネーションにも対応しており(HN の「More」ボタンを自動クリック)、サブページのスクレイピングも可能です(各記事のコメントページへ移動して議論データを取得)。 が必要なケースでは、方法2の再帰的 API コードに相当する処理を、1行も書かずに実現できます。

選び方はシンプルです。Python は、独自ロジック、複雑なデータ変換、定期実行パイプライン、あるいはプログラミング学習に向いています。Thunderbit は、すぐにデータが欲しい、コードを保守したくない、または開発者ではない人に向いています。状況に合ったツールを選びましょう。

Python・API・ノーコードの比較: どの方法を選ぶべき?

判断しやすいよう、完全版の比較表をまとめました。

比較項目BeautifulSoup(HTML)Firebase APIAlgolia APIThunderbit(ノーコード)
必要な技術レベル中級 Python初級 Python初級 Python不要
セットアップ時間10〜15分5〜10分5〜10分2分
保守負担中(セレクタが壊れる)低(安定した JSON)低(安定した JSON)なし
データの深さトップページのみ任意の item、ユーザー検索 + 過去データトップページ + サブページ
コメント難しい簡単(再帰)簡単(入れ子ツリー)サブページスクレイピング
過去データなしなしあり(完全アーカイブ)なし
出力方法自作が必要自作が必要自作が必要標準搭載(Excel、Sheets など)
定期実行cron / GitHub Actionscron / GitHub Actionscron / GitHub Actions標準スケジューラあり
向いている用途スクレイピング学習安定したパイプライン調査・分析素早いデータ取得

Python を学んでいる途中、あるいは独自の処理を作りたいなら、方法1か2がおすすめです。過去データの分析が必要なら、Algolia API を追加しましょう。コードなしでデータだけ欲しいなら、

まとめ: ここまでで手に入れたもの

ここまでで、あなたの手元には次のものがそろいました。

  • Hacker News をスクレイピングする2つの完全な Python 手法 — HTML 解析用の BeautifulSoup と、クリーンな JSON を返す Firebase API
  • ページ1を超えて取得するためのページネーション手法 — 2007年までさかのぼれる Algolia API を含む
  • CSV、Excel、Google Sheets への出力コード — ターミナルの表示だけではチームで共有できないからです
  • 本番運用向けのパターン — リトライ、キャッシュ、クロールと解析の分離、cron や GitHub Actions による定期実行
  • Python が過剰な場面向けのノーコード代替

私のおすすめは、多くの用途でまず Firebase API(方法2)から始めることです。よりきれいで信頼性が高く、入れ子の HTML を解析する面倒もなくコメントを取得できます。過去データが必要になったら Algolia API を追加しましょう。そして、サッとスプレッドシートが欲しいだけで Python プロジェクトを立ち上げたくないときのために、 はブックマークしておくと便利です。

さらに深く掘り下げたいなら、HN コメントを 用に収集したり、GitHub Actions で毎日のダイジェストパイプラインを構築したり、Algolia API を使って過去10年の技術トレンドの変化を追ってみてください。

高速な Hacker News スクレイピングに Thunderbit を試す

FAQ

Hacker News のスクレイピングは合法ですか?

HN のデータは公開されており、Y Combinator はプログラムからのアクセスを想定した公式 API も提供しています。サイトの では、読み取り専用コンテンツ(トップページ、アイテムページ、ユーザーページ)のスクレイピングは許可されていますが、30秒のクロール間隔を求めています。この間隔を守り、投票やログインなどの対話的なエンドポイントを取得しなければ、問題はありません。スクレイピングの倫理については、 のガイドも参考にしてください。

Hacker News には公式 API がありますか?

はい。hacker-news.firebaseio.com/v0/ にあり、無料で認証不要です。記事、コメント、ユーザープロフィール、すべてのフィードタイプ(top, new, best, ask, show, jobs)にアクセスできます。クリーンな JSON を返し、明示的なレート制限はありませんが、リクエスト頻度を抑えて丁寧に使うのが望ましいです。

Python で Hacker News のコメントをスクレイピングするには?

Firebase API を使って記事 item を取得し、kids フィールド(トップレベルコメント ID の配列)を取り出します。各コメントも item であり、返信用の kids フィールドを持っています。コメントとその子要素を再帰的に取得する関数でツリーをたどりましょう。完全なコードは上の「コメントを取得する(再帰的にツリーをたどる)」セクションを参照してください。あるいは、 を使えば、完全なネスト済みコメントツリーを1回のリクエストで取得できます。コメントが多い投稿ではこちらのほうがかなり速いです。

コードを書かずに Hacker News をスクレイピングできますか?

はい。 は Chrome 拡張として動作します。HN を開いて「AI Suggest Fields」をクリックするだけで、タイトル、URL、スコア、投稿者などの列を自動認識します。「Scrape」を押せば、Excel、Google Sheets、Airtable、Notion にそのまま出力できます。ページネーションにも対応しており、サブページに移動してコメントデータを取得することも可能です。Python もセレクタも保守も不要です。

過去の Hacker News データはどうやって取得しますか?

が最適です。search_by_date エンドポイントと numericFilters=created_at_i>TIMESTAMP を使えば、日付範囲で絞り込めます。キーワード検索、記事種別のフィルタ、最大500ページまでのページネーションが可能です。大量の過去分析には、(完全アーカイブ)、(2,800万件)、(400万件の投稿)にある公開データセットも利用できます。

もっと知る

Shuai Guan
Shuai Guan
Co-founder/CEO @ Thunderbit. Passionate about cross section of AI and Automation. He's a big advocate of automation and loves making it more accessible to everyone. Beyond tech, he channels his creativity through a passion for photography, capturing stories one picture at a time.
目次

Thunderbitを試す

リードや各種データをたった2クリックで取得。AI搭載。

Thunderbitを入手 無料です
AIでデータを抽出
Google Sheets、Airtable、Notionへ簡単にデータを転送
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week