我如何使用 Python 抓取 Hacker News(2 種方法,附完整程式碼)

最後更新於 April 16, 2026

幾個月前,我想替 Thunderbit 團隊做一份每天更新的 Hacker News 熱門故事摘要。剛開始,我本能地想說:先把網站加入書籤,然後每天早上看一下就好。結果撐了大概三天,我就發現自己每天都要花 20 分鐘,只是在看標題,還得把連結一條一條複製到試算表裡。

Hacker News 是網路上最精煉、也最有價值的科技情報來源之一——每月大約有 ,每天約有 1,300 則新故事被提交,並產生大約 13,000 則留言。無論你是想追蹤新興技術趨勢、監測品牌聲量、從「Who’s Hiring」討論串建立招募名單,還是單純想掌握開發者社群在關注什麼,光靠人工追蹤幾乎是不可能的任務。

好消息是:用 Python 抓取 Hacker News 其實比想像中簡單很多。這篇指南會帶你走過兩種完整方法——使用 BeautifulSoup 做 HTML 抓取,以及使用官方 HN Firebase API——另外也會涵蓋分頁、資料匯出、適合正式環境的做法,還有一個當你覺得 Python 有點大材小用時,可以直接上手的免寫程式替代方案。

為什麼要用 Python 抓取 Hacker News?

Hacker News 不只是另一個連結聚合站。它是一個由社群共同篩選的資訊流,最有意思的科技故事會透過投票與熱烈討論一路浮上檯面。使用者輪廓很明顯偏向科技專業人士(約 ),而網站有 66% 的直接流量,也說明這是一群忠誠、習慣回訪的讀者,而不是隨便路過看看的人。

以下是大家會去抓取 HN 資料的原因:

使用情境你能拿到什麼
每日科技摘要把熱門故事、分數與連結送到你的信箱或 Slack
品牌/競品監測當你的公司或產品被提及時即時提醒
趨勢分析追蹤哪些技術、語言或主題正在累積熱度
招募從「Who’s Hiring」討論串中整理職缺、技術棧與薪資訊號
內容研究找出表現好的主題,作為寫作或分享的方向
情緒分析判斷社群對產品、發表或產業變化的看法

像 Stripe、Dropbox、Airbnb 這些合計市值超過 4,000 億美元的公司,都曾把 Hacker News 視為早期回饋與使用者的重要來源。Drew Houston 曾在 2007 年 4 月把 Dropbox demo 發到 HN,結果直接衝上榜首,beta 等候名單在一天內從 5,000 人暴增到 75,000 人。HN 資料不只是有趣,還有很明確的商業價值。

這些資料雖然是公開的,但網站結構讓人工蒐集非常費時。用 Python 自動化,才是最實際的做法。

用 Python 抓取 Hacker News 的兩種方式:總覽

本指南會介紹兩種可以直接執行的完整方法:

  1. 使用 requests + BeautifulSoup 做 HTML 抓取——抓取 news.ycombinator.com 的原始 HTML,解析後萃取故事資料。很適合學習抓取基礎,也適合精準取得頁面上顯示的內容。
  2. 使用官方 Hacker News Firebase API——直接呼叫 JSON 端點,不需要解析 HTML。這種方式更適合穩定的資料管線、留言抓取與歷史資料分析。

下面這張比較表能幫你判斷哪種方式更適合你的需求:

比較項目HTML 抓取(requests + BS4)HN Firebase APIThunderbit(免寫程式)
設定難度中等(需解析 HTML 選擇器)低(JSON 端點)幾乎沒有(2 步 Chrome 擴充功能)
資料即時性即時首頁資料即時(可依 ID 取得任何項目)即時
速率限制風險中等(robots.txt 要求 30 秒抓取延遲)低(官方、限制寬鬆)由 Thunderbit 管理
留言抓取困難(巢狀 HTML)容易(遞迴項目 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 抓取 Hacker News

這是最經典的做法——先抓 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。每則故事都由兩個關鍵的 <tr> 列組成:

  • 故事列<tr class="athing submission">):包含排名、標題與連結
  • 資訊列(下一個 <tr>):包含分數、作者、時間與留言數

重要的選擇器如下:

  • span.titleline > a —— 故事標題與 URL
  • span.score —— 投票數(例如「118 points」)
  • a.hnuser —— 作者帳號
  • span.age —— 發文時間
  • .subtext 中最後一個包含「comment」字樣的 <a> —— 留言數

如果你在 Chrome 上對任一故事標題按右鍵並選擇「Inspect(檢查)」,你會看到類似這樣的 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(不換行空白),因此要用這個字元來分割。
  • 連到 HN 其他頁面的故事(例如「Ask HN」)會使用 item?id= 開頭的相對網址。你可能會想在前面補上 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 搭配 Python 抓取 Hacker News

HN Firebase API 是官方認可的 Hacker News 資料存取方式。沒有驗證、沒有 API 金鑰、也不需要解析 HTML。你會直接拿到乾淨的 JSON 回應。我在需要穩定跑在正式環境的情境下,通常都會用這個方法。

你需要知道的核心 API 端點

基礎網址是 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。每則留言本身也是一個 item,並且可能還有自己的 kids——這就是留言樹的結構。

步驟 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

一次請求就拿到 500 個故事 ID——不需要解析,不需要選擇器,直接就是一個 JSON 陣列。

步驟 2:依 ID 抓取故事詳情

接著我們需要實際的故事資料。這時會遇到 fan-out 問題:500 則故事就代表要發出 500 次 API 呼叫。根據我的測試,每次 item 請求連續執行時大約要 1.2 秒。500 則故事大概要 10 分鐘。

多數情境根本不需要全部 500 則。下面的程式會抓取前 30 則:

1def fetch_story(story_id):
2    """從 HN API 抓取單一故事詳情。"""
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 相較於 HTML 抓取特別有優勢的地方。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 class 就讓你的爬蟲壞掉。

超越第 1 頁:分頁與歷史資料

大多數 HN 抓取教學都只做到第 1 頁——也就是 30 則故事。這對快速示範夠用,但真正的情境通常需要更深入的資料。

使用 BeautifulSoup 抓取多個頁面

HN 的分頁網址很簡單:?p=2?p=3 以此類推。每頁會有 30 則故事,而網站最多大約提供到第 20 頁(總共約 600 則故事)。再往後就會是空頁。

1import time
2def scrape_hn_pages(num_pages=5):
3    """抓取 Hacker News 首頁的多個頁面。"""
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)或暫時封鎖。五個頁面每 30 秒抓一次,總共大約要 2.5 分鐘——不算快,但很有禮貌。

如果你不想自己處理分頁程式碼, 可以自動處理點擊式與無限滾動分頁。它會自動點 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 速度很快(伺服器處理時間約 59 毫秒)、不需要 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 service account(一次性流程):

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")

免寫程式的匯出替代方案

如果光是設定 service account 和寫匯出程式,就比抓資料本身還麻煩,我完全懂。在 Thunderbit,我們做了免費的資料匯出功能,能把抓好的資料直接送到 Excel、Google Sheets、Airtable 或 Notion——不用寫程式、不用憑證、也不用維護管線。若只是單次抓取,這真的會快很多。下面還會再多說一些。

讓爬蟲更接近正式環境:錯誤處理、快取與排程

如果你只是玩一次,前面的程式已經夠用;但如果你要把它每天放進工作流程,就還需要幾個關鍵元件。

錯誤處理與重試邏輯

網路會失敗,伺服器會限流,單次錯誤不應該讓整個抓取流程整個垮掉。以下是一個帶有指數退避的重試函式:

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    """自動重試並採用指數退避來抓取網址。"""
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 只要兩行就能解決:

1import requests_cache
2requests_cache.install_cache("hn_cache", expire_after=3600)  # 快取 1 小時

把這兩行加到腳本最前面後,所有 requests.get() 呼叫都會自動快取到本機 SQLite 資料庫裡。你在一小時內重跑 10 次,真正打到網路的只會是第一次。這也是論壇使用者常常推薦的工具,而且真的很有道理。

把抓取與解析分開

有經驗的爬蟲工程師很推的一個做法:先下載原始資料,再進行解析。這樣一來,如果解析邏輯有 bug,你可以修正後直接重新解析,不必重抓資料。

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  # 跳過已抓取項目
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這種「先抓後解析」的兩階段流程,特別適合你要處理數百筆資料、又想快速迭代資料處理邏輯的情境。
14### 把爬蟲排程化
15如果你要做每日 HN 摘要,就需要讓爬蟲自動執行。常見做法有兩種:
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 分鐘延遲(所以像 :30 這種非整點時間通常比 :00 更穩),而且 GitHub 可能會停用 60 天沒有活動的專案之排程工作流程。務必加入 workflow_dispatch,這樣你測試時才能手動觸發。

如果你想要更簡單的方式,Thunderbit 的 Scheduled Scraper 功能可以直接用自然語言描述排程,例如「每天早上 8 點抓一次」,完全不需要自己架伺服器或設定 cron。

當 Python 太重時:免寫程式抓取 Hacker News 的方式

老實說,就算我是 Python 愛好者,而且我們團隊也在做開發者工具,如果你只是想把今天前 100 則 HN 熱門故事匯出到試算表,而且只做一次,那用 Python 其實有點多此一舉。光是環境設定(虛擬環境、安裝套件、找選擇器)就比真正抓資料還花時間。

這就是 的用武之地。流程大概是這樣:

  1. 在 Chrome 打開 news.ycombinator.com
  2. 點 Thunderbit 擴充功能圖示,然後選「AI Suggest Fields」
  3. AI 會自動讀取頁面並建議欄位:Title、URL、Score、Author、Comment Count、Time Posted
  4. 你可以自行調整欄位(重新命名、刪除或新增自訂欄位——甚至可以加上像「Categorize as AI/DevTools/Web/Other」這樣的 AI 提示詞)
  5. 點「Scrape」——資料就會變成結構化表格
  6. 匯出到 Excel、Google Sheets、Airtable 或 Notion

兩次點擊就能拿到結構化資料。沒有選擇器、沒有程式碼、沒有維護成本。

這裡真正的優勢是:Thunderbit 的 AI 會自動適應版面變動。傳統的 CSS 選擇器爬蟲,一旦網站改了標記就很容易壞掉——雖然 HN 的 HTML 相對穩定,但它確實改過(像 class="athing submission" 有更新,span.titleline 也取代了舊的 a.storylink)。AI 爬蟲每次都會重新讀頁面,所以不會被 class 名稱改動影響。

python-vs-thunderbit-comparison.webp

Thunderbit 也能處理分頁(自動點擊 HN 的「More」按鈕)與子頁面抓取(逐一進入每篇故事的留言頁,抓取討論資料)。如果是 這類情境,它其實就相當於方法 2 的遞迴 API 程式碼,只是你不用寫任何一行。

取捨很直接:當你需要自訂邏輯、複雜資料轉換、排程化自動管線,或你本來就在學寫程式時,Python 是正確選擇;當你需要快速拿資料、不想維護程式,或者你不是開發者時,Thunderbit 會更適合。選擇最符合你情境的工具就好。

Python vs. API vs. 免寫程式:你該選哪一種?

下面是完整的決策表:

比較項目BeautifulSoup(HTML)Firebase APIAlgolia APIThunderbit(免寫程式)
所需技術能力中級 Python初階 Python初階 Python不需要
設定時間10–15 分鐘5–10 分鐘5–10 分鐘2 分鐘
維護成本中等(選擇器可能失效)低(穩定 JSON)低(穩定 JSON)幾乎沒有
資料深度只有首頁任意項目、使用者搜尋 + 歷史資料首頁 + 子頁面
留言困難容易(遞迴)容易(巢狀樹)子頁面抓取
歷史資料是(完整封存)
匯出選項自己寫程式自己寫程式自己寫程式內建(Excel、Sheets 等)
排程cron / GitHub Actionscron / GitHub Actionscron / GitHub Actions內建排程器
最適合學習爬蟲穩定資料管線研究與分析快速抓資料

如果你在學 Python,或是在做客製化工具,就選方法 1 或 2;如果你要做歷史分析,再加上 Algolia API;如果你只是想直接拿資料、不想寫程式,試試

結論與重點整理

現在你手上已經有這些工具:

  • 兩種完整的 Python 方法來抓取 Hacker News——用 BeautifulSoup 解析 HTML,或用 Firebase API 取得乾淨的 JSON 資料
  • 分頁技巧,可以抓超過第 1 頁,還能透過 Algolia API 往回分析 2007 年以來的歷史資料
  • 匯出程式碼,可輸出成 CSV、Excel 與 Google Sheets——因為資料只待在終端機裡,對團隊其他人沒什麼幫助
  • 正式環境做法——重試邏輯、快取、抓取/解析分離,以及透過 cron 或 GitHub Actions 排程自動化
  • 免寫程式替代方案,當 Python 對你的需求來說太重時可直接使用

我的建議是:多數情況先從 Firebase API(方法 2)開始。它更乾淨、更穩定,而且可以直接抓留言,不必費力解析巢狀 HTML。當你需要歷史資料時,再加入 Algolia API。至於 ,建議先收藏起來,當你只想快速拿一份試算表、又不想啟動整個 Python 專案時,它會非常好用。

如果你想更進一步,可以試著抓 HN 留言做 ,用 GitHub Actions 建立每日摘要管線,或研究 Algolia API,追蹤過去十年間科技趨勢如何變化。

試試 Thunderbit,快速抓取 Hacker News

常見問題

抓取 Hacker News 合法嗎?

HN 的資料是公開可存取的,而且 Y Combinator 也提供了官方 API,專門用於程式化存取。網站的 允許抓取只讀內容(首頁、項目頁、使用者頁),但要求 30 秒的抓取延遲。只要你尊重這個延遲、不抓互動式端點(投票、登入),基本上就沒問題。若想進一步了解抓取倫理,可參考我們的 指南。

Hacker News 有官方 API 嗎?

有。 位於 hacker-news.firebaseio.com/v0/,免費、無須驗證,可存取故事、留言、使用者個人資料,以及所有 feed 類型(top、new、best、ask、show、jobs)。它回傳乾淨的 JSON,而且沒有明示的速率限制,但仍建議以禮貌的頻率發送請求。

我要怎麼用 Python 抓取 Hacker News 留言?

使用 Firebase API 時,先抓故事項目取得它的 kids 欄位(也就是頂層留言 ID 陣列)。每則留言本身也是一個 item,且有自己的 kids 欄位代表回覆。你可以寫一個函式,以遞迴方式抓取每則留言與其子留言。上面的「抓取留言(遞迴樹狀走訪)」章節有完整範例。或者,你也可以用 一次取得完整的巢狀留言樹,處理留言很多的文章會快非常多。

不寫程式也能抓 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