Hur jag skrapar Hacker News med Python (2 metoder, komplett kod)

Senast uppdaterad April 16, 2026

För några månader sedan ville jag bygga ett dagligt nyhetsutskick med de bästa Hacker News-artiklarna för vårt team på Thunderbit. Min första tanke var helt enkelt att bokmärka sajten och bläddra igenom den varje morgon. Det höll i ungefär tre dagar innan jag insåg att jag lade 20 minuter om dagen på att läsa rubriker och kopiera in länkar i ett kalkylark.

Hacker News är en av de mest koncentrerade och värdefulla källorna till tech-intelligens på internet — ungefär , runt 1 300 nya inlägg varje dag och cirka 13 000 kommentarer per dag. Oavsett om du vill följa nya tekniktrender, bevaka ditt varumärke, bygga en rekryteringspipeline från trådar som "Who's Hiring", eller bara försöka hålla koll på vad utvecklarvärlden bryr sig om, är manuell uppföljning en kamp du inte vinner.

Det goda nyheterna: att skrapa Hacker News med Python är förvånansvärt enkelt. I den här guiden går jag igenom två kompletta metoder — HTML-skrapning med BeautifulSoup och den officiella HN Firebase API:n — samt paginering, export av data, produktionsklara mönster och ett no-code-alternativ för när Python känns som överkurs.

Varför skrapa Hacker News med Python?

Hacker News är inte bara ännu en länksamlar-sajt. Det är ett kuraterat flöde drivet av communityn där de mest intressanta tekniknyheterna lyfts fram genom uppröster och aktiv diskussion. Publiken lutar starkt åt teknikproffs (ungefär ), och sajtens 66 % direkta trafik visar att detta är en lojal, återkommande läsarskara — inte tillfälliga besökare.

Här är några vanliga anledningar till att folk skrapar HN-data:

AnvändningsområdeVad du får
Dagligt tech-digestToppartiklar, poäng och länkar skickade till din inkorg eller Slack
Bevakning av varumärke/konkurrenterAviseringar när ditt företag eller din produkt nämns
TrendanalysFölj vilka tekniker, språk eller ämnen som får fäste över tid
RekryteringPlocka ut jobbannonser, tech stacks och löneindikatorer ur trådar med "Who's Hiring"
InnehållsresearchHitta ämnen som presterar bra att skriva om eller dela
SentimentanalysBedöm communityns åsikt om produkter, lanseringar eller förändringar i branschen

Bolag värda över 400 miljarder dollar tillsammans — Stripe, Dropbox och Airbnb — tillskriver Hacker News viktig tidig feedback och sina första användare därifrån. Drew Houston lade upp Dropbox-demo på HN i april 2007, den nådde förstaplatsen och betaväntelistan exploderade från 5 000 till 75 000 användare på en enda dag. HN-data är alltså inte bara intressant — den är kommersiellt värdefull.

Datan är offentligt tillgänglig, men sajtens struktur gör manuell insamling trög och tidskrävande. Automation med Python är den praktiska lösningen.

Två sätt att skrapa Hacker News med Python: översikt

Den här guiden täcker två kompletta, körbara arbetssätt:

  1. HTML-skrapning med requests + BeautifulSoup — hämta rå HTML från news.ycombinator.com och parsa den för att extrahera story-data. Perfekt för att lära sig grunderna i web scraping och för att få exakt det som visas på sidan.
  2. Den officiella Hacker News Firebase API:n — anropa JSON-endpoints direkt, utan att behöva parsa HTML. Bättre för stabila datapipelines, åtkomst till kommentarer och historisk data.

Här är en jämförelse sida vid sida för att hjälpa dig välja rätt metod:

KriteriumHTML-skrapning (requests + BS4)HN Firebase APIThunderbit (No-code)
Komplexitet vid uppstartMedel (parsa HTML-selectors)Låg (JSON-endpoints)Ingen (2-klicks Chrome-tillägg)
Datans färskhetRealtime på förstasidanRealtime (valfritt objekt via ID)Realtime
Risk för rate limitMedel (robots.txt anger 30 s crawl delay)Låg (officiell, generös)Hanteras av Thunderbit
Åtkomst till kommentarerSvårt (nästlad HTML)Enkelt (rekursiva item-ID:n)Funktion för skrapning av undersidor
Historisk dataBegränsadVia Algolia Search APIEj tillämpligt
Bäst förLära sig grunderna i scrapingPålitliga datapipelinesIcke-utvecklare, snabba exporter

Båda metoderna innehåller komplett, körbar Python-kod. Och om du bara vill ha datan utan att skriva någon kod alls, tar jag upp det också.

Innan du börjar

  • Svårighetsgrad: Nybörjare till medel
  • Tidsåtgång: cirka 15–20 minuter per metod
  • Det här behöver du:
    • Python 3.11+ installerat
    • En terminal eller kodredigerare
    • Chrome-webbläsare (om du vill inspektera HN:s HTML eller testa no-code-alternativet)
    • (valfritt, för no-code-metoden)

scrape-hacker-news-methods.webp

Så ställer du in din Python-miljö

Innan vi börjar ta i HN-datan, låt oss förbereda miljön. Jag rekommenderar att du skapar en virtuell miljö så att projektets beroenden hålls rena.

1# Skapa och aktivera en virtuell miljö
2python3 -m venv hn-scraper
3# macOS/Linux:
4source hn-scraper/bin/activate
5# Windows:
6hn-scraper\Scripts\activate
7# Installera paketen vi behöver för båda metoderna
8pip install requests==2.33.1 beautifulsoup4==4.14.3 pandas==3.0.2 openpyxl==3.1.5

För produktionsmönster längre fram (cache och retries) vill du även ha:

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

Inga särskilda API-nycklar, inga autentiseringstokens. HN:s data är öppen.

Metod 1: Skrapa Hacker News med Python med BeautifulSoup

Det här är det klassiska sättet — hämta HTML, parsa den och plocka ut datan du vill ha. Det är så de flesta lär sig web scraping, och HN:s enkla tabellbaserade layout gör den till en bra övningsmiljö.

Steg 1: Hämta Hacker News-förstasidan

Öppna din editor och skapa en fil som heter scrape_hn_bs4.py. Här är startkoden:

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

Kör den. Du bör se Status: 200 och en sidlängd på ungefär 40 000–50 000 tecken. Det är den råa HTML-koden från HN:s förstasida, laddad i minnet och redo att parsa.

Steg 2: Förstå HTML-strukturen

HN använder en tabellbaserad layout — ingen modern CSS grid eller flexbox. Varje story på sidan består av två viktiga <tr>-rader:

  • Story-raden (<tr class="athing submission">): innehåller placering, titel och länk
  • Metadata-raden (nästa <tr>): innehåller poäng, författare, tid och antal kommentarer

De viktiga selectors är:

  • span.titleline > a — storyns titel och URL
  • span.score — röstpoängen (t.ex. "118 points")
  • a.hnuser — författarens användarnamn
  • span.age — när inlägget publicerades
  • Den sista <a> i .subtext med ordet "comment" i texten — antal kommentarer

Om du högerklickar på en storytitel i Chrome och väljer "Inspect" ser du något i stil med detta:

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

Och metadata-raden under den:

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>

Att förstå dessa selectors är avgörande — om HN någon gång ändrar sin markup måste du uppdatera dem. (Spoiler: API-metoden slipper det problemet helt.)

Steg 3: Extrahera titlar, länkar och poäng

Nu till själva jobbet. Vi loopar igenom varje story-rad, hämtar titel och länk från story-raden och sedan poängen från metadata-raden direkt under.

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    # Titel och URL från story-raden
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    # Metadata från nästa rad
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# Filtrera fram stories med minst 50 poäng, sorterade efter score
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])

Några kommentarer till koden:

  • Walrus-operatorn (:=) fungerar i Python 3.8+. Den låter oss tilldela och kontrollera i samma rad — praktiskt för valfria element som span.score som inte finns på alla rader (t.ex. jobbannonser saknar score).
  • HN använder \xa0 (icke-brytande mellanslag) mellan siffran och ordet "comments", så vi delar på det.
  • Stories som länkar till andra HN-sidor (t.ex. "Ask HN"-poster) har relativa URL:er som börjar med item?id=. Du kan vilja lägga till https://news.ycombinator.com/ framför dem.

Steg 4: Kör och se resultat

Spara och kör:

1python scrape_hn_bs4.py

Du bör se ett resultat i stil med:

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 ...]

Det där är 30 stories från sida 1. Men HN har hundratals aktiva stories vid varje given tidpunkt. Paginering tar vi upp i en senare del.

Metod 2: Skrapa Hacker News med Python med den officiella API:n

HN Firebase API är det officiellt sanktionerade sättet att komma åt Hacker News-data. Ingen autentisering, inga API-nycklar, ingen HTML-parsning. Du får rena JSON-svar. Jag använder den här metoden för allt som måste fungera stabilt i produktion.

Viktiga API-endpoints du behöver känna till

Bas-URL:en är https://hacker-news.firebaseio.com/v0/. Här är de endpoints som spelar roll:

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

Ett story-objekt ser ut så här:

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}

Fältet kids innehåller ID:n för direkt underliggande kommentarer. Varje kommentar är i sig ett item som kan ha egna kids — det är så kommentarsträdet är uppbyggt.

Steg 1: Hämta ID:n för toppstories

Skapa en fil som heter scrape_hn_api.py:

1import requests
2import time
3from pprint import pprint
4API_BASE = "https://hacker-news.firebaseio.com/v0"
5# Hämta ID:n för toppstories
6response = requests.get(f"{API_BASE}/topstories.json")
7story_ids = response.json()
8print(f"Fick {len(story_ids)} ID:n för toppstories")
9# Output: Fick 500 ID:n för toppstories

500 story-ID:n i en enda request — ingen parsning, inga selectors, bara en JSON-array.

Steg 2: Hämta story-detaljer via ID

Nu behöver vi själva storydatan. Här visar sig fan-out-problemet: 500 stories innebär 500 enskilda API-anrop. I mina tester tog varje item-request ungefär 1,2 sekunder sekventiellt. För 500 stories blir det ungefär 10 minuter.

För de flesta användningsfall behöver du inte alla 500. Här är kod för att hämta de 30 översta:

1def fetch_story(story_id):
2    """Hämta detaljer för en enskild story från 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# Sortera efter score, visa topp 10
7top = sorted(stories, key=lambda x: x["score"], reverse=True)[:10]
8pprint(top)

time.sleep(0.1) lägger in en liten hövlig paus. Firebase API:t har ingen uttalad rate limit, men att bombardera vilket API som helst utan pauser är dålig stil.

Steg 3: Skrapa kommentarer (rekursiv trädvandring)

Här blir API:t verkligen bättre än HTML-skrapning. Kommentarer på HN är djupt nästlade — svar på svar på svar. I HTML innebär det att man måste parsa komplexa nästlade tabellstrukturer. Med API:t ger varje kommentars kids-fält ID:n för dess barn, och du kan bara vandra trädet rekursivt.

1def fetch_comments(item_id, depth=0, max_depth=3):
2    """Hämta kommentarer rekursivt upp till 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# Exempel: hämta kommentarer för top-storyn
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"\nKommentarer för: {top_story['title']}")
18        all_comments = []
19        for kid_id in top_story_full["kids"][:5]:  # Första 5 kommentarerna på toppnivå
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}...")

Det här rekursiva arbetssättet är betydligt enklare än att försöka parsa nästlade kommentarstrådar i HTML. Om du behöver hela kommentarsträd är API:t rätt väg.

Steg 4: Kör och se resultat

1python scrape_hn_api.py

Du kommer att se strukturerad story-data följt av en nästlad kommentarförhandsvisning. Datan är renare, åtkomsten till kommentarer är trivial och det finns ingen risk att din scraper går sönder bara för att HN bytt namnet på en CSS-klass.

Bortom sida 1: paginering och historisk data

De flesta guider för HN-skrapning stannar vid sida 1 — 30 stories. Det duger för en snabb demo, men verkliga användningsfall behöver ofta mer djup.

Skrapa flera sidor med BeautifulSoup

HN:s paginering använder ett enkelt URL-mönster: ?p=2, ?p=3 osv. Varje sida returnerar 30 stories, och sajten serverar upp till ungefär sida 20 (sammanlagt runt 600 stories). Efter det får du tomma sidor.

1import time
2def scrape_hn_pages(num_pages=5):
3    """Skrapa flera sidor från HN:s förstasida."""
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"Sida {page}: inga stories hittades, stoppar.")
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"Sida {page}: skrapade {len(story_rows)} stories")
23        # Respektera robots.txt:s crawl-delay på 30 sekunder
24        if page < num_pages:
25            time.sleep(30)
26    return all_stories
27stories = scrape_hn_pages(5)
28print(f"\nTotalt antal skrapade stories: {len(stories)}")

time.sleep(30) är viktigt. HN:s begär uttryckligen 30 sekunders crawl delay. Ignorerar du det riskerar du rate limiting (HTTP 429) eller tillfälligt blockering. Fem sidor med 30 sekunders mellanrum tar ungefär 2,5 minuter — inte direkt, men respektfullt.

För dig som inte vill hantera pagineringskod själv hanterar klickbaserad och oändlig scroll-paginering automatiskt. Den klickar på "More"-knappen längst ner på HN-sidorna utan någon konfiguration.

Åtkomst till historisk Hacker News-data med Algolia API

Firebase API:t ger dig aktuell data. För historisk analys — "Vilka var de bästa Python-artiklarna 2023?" eller "Hur har AI-bevakningen förändrats de senaste 5 åren?" — behöver du .

1import requests
2ALGOLIA_BASE = "https://hn.algolia.com/api/v1"
3> This paragraph contains content that cannot be parsed and has been skipped.
4# Exempel: hitta Python-skrapningsstories med 10+ poäng sedan jan 2024
5results = search_hn(
6    query="python scraping",
7    tags="story",
8)
9print(f"Hittade {results['nbHits']} resultat totalt")
10for hit in results["hits"][:5]:
11    print(f"  [{hit.get('points', 0)} poäng] {hit['title']}")

För datumfiltrerade sökningar använder du numericFilters:

1import calendar, datetime
2# Stories sedan 1 januari 2024
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:t är snabbt (59 ms serverbearbetningstid), kräver ingen API-nyckel och stödjer paginering upp till 500 sidor. För historisk bulk-analys är det bästa alternativet.
7## Exportera skrapad Hacker News-data till CSV, Excel och Google Sheets
8Varje HN-guidning jag sett slutar med `pprint()`-utskrift i terminalen. Det är bra för felsökning, men om du bygger ett dagligt digest eller gör trendanalys behöver du datan i en fil. Så här gör du det.
9### Exportera till CSV med Python
10```python
11import csv
12def export_to_csv(stories, filename="hn_stories.csv"):
13    """Spara skrapade stories till en CSV-fil."""
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"Sparade {len(stories)} stories till {filename}")
20export_to_csv(stories)

Exportera till Excel med Python

1import pandas as pd
2def export_to_excel(stories, filename="hn_stories.xlsx"):
3    """Spara skrapade stories till en Excel-fil."""
4    df = pd.DataFrame(stories)
5    df.to_excel(filename, index=False, engine="openpyxl")
6    print(f"Sparade {len(stories)} stories till {filename}")
7export_to_excel(stories)

Se till att openpyxl är installerat — pandas använder det som Excel-motor. Om det saknas får du ett ImportError.

Skicka till Google Sheets (valfritt)

För automatiserade arbetsflöden kanske du vill skicka datan direkt till Google Sheets med biblioteket gspread. Då behöver du sätta upp ett Google Cloud service account (en engångsprocess):

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

No-code-alternativet för export

Om det låter som mer jobb att sätta upp service accounts och skriva exportkod än själva skrapningen, så förstår jag det. På Thunderbit har vi byggt gratis dataexport som låter dig skicka skrapad data direkt till Excel, Google Sheets, Airtable eller Notion — ingen kod, inga credentials, ingen pipeline att underhålla. För en engångshämtning är det faktiskt snabbare. Mer om det längre ner.

Gör din scraper produktionsklar: felhantering, cache och schemaläggning

Om du kör en scraper en gång för skojs skull duger koden ovan. Om du kör den dagligen som del av ett arbetsflöde behöver du några saker till.

Felhantering och retry-logik

Nätverk går ner. Servrar stryper trafik. Ett enda misslyckat anrop ska inte krascha hela din scraping. Här är en retry-funktion med exponentiell backoff:

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    """Hämta en URL med automatiska retries och exponentiell backoff."""
6    response = requests.get(url, timeout=10)
7    response.raise_for_status()
8    return response
9# Användning:
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"Misslyckades efter retries: {e}")

Biblioteket tenacity hanterar retry-logiken snyggt. Det försöker upp till 5 gånger med jitterad exponentiell backoff — från 1 sekund och upp till 60 sekunder. Det hanterar HTTP 429 (rate limited), 503 (service unavailable) och tillfälliga nätverksfel på ett bra sätt.

Cacha svar för att slippa skrapa om och om igen

Under utveckling kör du ofta scrapern många gånger medan du justerar parsningen. Utan cache träffar varje körning HN:s servrar igen för samma data. Biblioteket requests-cache löser det på två rader:

1import requests_cache
2requests_cache.install_cache("hn_cache", expire_after=3600)  # Cacha i 1 timme

Efter att du lagt till de här raderna högst upp i skriptet cachas alla requests.get()-anrop automatiskt i en lokal SQLite-databas. Kör du skriptet 10 gånger på en timme är det bara första körningen som faktiskt går ut på nätet. Det här är ett verktyg , och med god anledning.

Separera insamling från parsning

Ett mönster erfarna scraper-utvecklare svär vid: hämta rådata först, parsa sedan. Då kan du, om parsningen har en bugg, fixa den och köra om utan att hämta om datan.

1import os, json
2def crawl_and_save(story_ids, output_dir="raw_data"):
3    """Hämta story-data och spara rå JSON på disk."""
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  # Hoppa över objekt som redan hämtats
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.
13Det här tvåstegsupplägget är särskilt värdefullt när du skrapar hundratals objekt och vill iterera snabbt på hur datan bearbetas.
14### Automatisera din scraper på schema
15För ett dagligt HN-digest behöver scrapern köras automatiskt. Två vanliga alternativ:
16**Alternativ 1: cron (Linux/Mac)**
17```bash
18# Kör varje dag kl. 08:30 UTC
1930 8 * * * /usr/bin/python3 /home/user/scrape_hn.py >> /home/user/scrape.log 2>&1

Alternativ 2: GitHub Actions (gratis, ingen server behövs)

1name: Scrape Hacker News
2on:
3  schedule:
4    - cron: '30 8 * * *'  # Dagligen kl. 08:30 UTC
5  workflow_dispatch:        # Manuell trigger-knapp
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 "Uppdatera HN-data $(date -u +%Y-%m-%dT%H:%M:%SZ)"
21          git push

Några fallgropar med schemaläggning i GitHub Actions: alla cron-tider är i UTC, förseningar på 15–60 minuter är vanliga (använd tider som :30 i stället för :00), och GitHub kan inaktivera schemalagda workflows för repos utan aktivitet i 60 dagar. Inkludera alltid workflow_dispatch så att du kan köra manuellt vid test.

För ett enklare alternativ låter Thunderbit’s Scheduled Scraper-funktion dig beskriva schemat i vanlig text — något i stil med "skrapa varje morgon kl. 8" — utan server eller cron-konfiguration.

När Python är överkurs: no-code-sättet att skrapa Hacker News

Jag ska vara ärlig här, även om jag älskar Python och mitt team bygger utvecklarverktyg. Om du bara behöver dagens 100 bästa HN-stories i ett kalkylark — direkt, en gång — är det onödigt mycket arbete att skriva, felsöka och köra ett Python-skript. Bara uppsättningen (virtuell miljö, installera paket, lista ut selectors) tar längre tid än själva datainsamlingen.

Det är här passar in. Så här fungerar det:

  1. Öppna news.ycombinator.com i Chrome
  2. Klicka på Thunderbit-ikonen och sedan "AI Suggest Fields"
  3. AI:n läser sidan och föreslår kolumner: Title, URL, Score, Author, Comment Count, Time Posted
  4. Justera fälten om du vill (byt namn, ta bort eller lägg till egna — du kan till och med lägga till en AI-prompt som "Klassificera som AI/DevTools/Web/Other")
  5. Klicka på "Scrape" — datan visas i en strukturerad tabell
  6. Exportera till Excel, Google Sheets, Airtable eller Notion

Två klick till strukturerad data. Inga selectors, ingen kod, inget underhåll.

En verklig fördel här: Thunderbits AI anpassar sig automatiskt när layouten ändras. Traditionella scrapers med CSS-selectors går sönder när en sajt ändrar markup — och även om HN:s HTML är ganska stabil har den ändrats (klassen class="athing submission" uppdaterades, span.titleline ersatte den äldre a.storylink). En AI-driven scraper läser sidan på nytt varje gång, så den bryr sig inte om ändringar i klassnamn.

python-vs-thunderbit-comparison.webp

Thunderbit hanterar också paginering (den klickar automatiskt på HN:s "More"-knapp) och skrapning av undersidor (den besöker varje stories kommentarsida för att hämta diskussionsdata). För use case med är det motsvarigheten till den rekursiva API-koden i metod 2 — men utan att du skriver en enda rad.

Avvägningen är enkel: Python är rätt val när du behöver egen logik, komplex datatransformering, schemalagda automatiserade pipelines eller om du lär dig koda. Thunderbit är rätt val när du vill ha data snabbt, inte vill underhålla kod eller inte är utvecklare. Välj det verktyg som passar situationen.

Python vs. API vs. no-code: vilken metod ska du välja?

Här är hela beslutsramverket:

KriteriumBeautifulSoup (HTML)Firebase APIAlgolia APIThunderbit (No-code)
Teknisk nivå som krävsMedelgod PythonNybörjar-PythonNybörjar-PythonIngen
Tid för uppsättning10–15 min5–10 min5–10 min2 min
UnderhållsbehovMedel (selectors kan gå sönder)Låg (stabil JSON)Låg (stabil JSON)Inget
DatadjupEndast förstasidanValfritt item, användareSök + historikFörstasida + undersidor
KommentarerSvårtEnkelt (rekursivt)Enkelt (nästlat träd)Skrapning av undersidor
Historisk dataNejNejJa (fullt arkiv)Nej
ExportalternativBygg själv i kodBygg själv i kodBygg själv i kodInbyggt (Excel, Sheets, etc.)
Schemaläggningcron / GitHub Actionscron / GitHub Actionscron / GitHub ActionsInbyggd schemaläggare
Bäst förLära sig scrapingPålitliga pipelinesResearch och analysSnabba datauttag

Om du lär dig Python eller bygger något skräddarsytt, välj metod 1 eller 2. Om du behöver historisk analys, lägg till Algolia API. Om du bara vill ha datan utan kod, .

Slutsats och viktigaste lärdomar

Nu har du följande i verktygslådan:

  • Två kompletta Python-metoder för att skrapa Hacker News — BeautifulSoup för HTML-parsning och Firebase API för rena JSON-data
  • Pagineringstekniker för att skrapa bortom sida 1, inklusive Algolia API för historisk data tillbaka till 2007
  • Exportkod för CSV, Excel och Google Sheets — eftersom data i terminalen inte hjälper någon annan i teamet
  • Produktionsmönster — retry-logik, cache, separation mellan crawl och parsing, samt schemalagd automation via cron eller GitHub Actions
  • Ett no-code-alternativ för när Python är mer verktyg än du behöver

Min rekommendation: börja med Firebase API (metod 2) för de flesta användningsfall. Det är renare, mer pålitligt och ger dig tillgång till kommentarer utan huvudvärken med att parsa nästlad HTML. Lägg till Algolia API när du behöver historisk data. Och spara i bokmärkena för de tillfällen då du bara behöver ett snabbt kalkylark och inte vill starta ett helt Python-projekt.

Om du vill gå djupare kan du testa att skrapa HN-kommentarer för , bygga en daglig digest-pipeline med GitHub Actions eller utforska Algolia API för att följa hur tekniktrender har förändrats under det senaste decenniet.

Testa Thunderbit för snabb skrapning av Hacker News

Vanliga frågor

Är det lagligt att skrapa Hacker News?

HN:s data är offentligt tillgänglig, och Y Combinator tillhandahåller ett officiellt API just för programmatisk åtkomst. Saj­tens tillåter skrapning av innehåll som bara kan läsas (förstasida, item-sidor, användarsidor) men begär 30 sekunders crawl delay. Respektera fördröjningen, skrapa inte interaktiva endpoints (röstning, inloggning), så är du på säker mark. För mer om etik kring scraping, se vår guide om .

Finns det ett officiellt API för Hacker News?

Ja. hacker-news.firebaseio.com/v0/ är gratis, kräver ingen autentisering och ger åtkomst till stories, kommentarer, användarprofiler och alla feed-typer (top, new, best, ask, show, jobs). Det returnerar ren JSON och har ingen uttalad rate limit, även om det alltid är klokt att vara försiktig med hur ofta du skickar anrop.

Hur skrapar jag Hacker News-kommentarer med Python?

Med Firebase API hämtar du ett story-objekt för att få dess kids-fält (en array med ID:n för kommentarer på toppnivå). Varje kommentar är i sin tur ett item med eget kids-fält för svar. Gå igenom trädet rekursivt med en funktion som hämtar varje kommentar och dess barn. Se avsnittet "Skrapa kommentarer (rekursiv trädvandring)" ovan för komplett kod. Alternativt returnerar hela nästlade kommentarsträdet i ett enda anrop — mycket snabbare för stories med många kommentarer.

Kan jag skrapa Hacker News utan att skriva kod?

Ja. fungerar som ett Chrome-tillägg — öppna HN, klicka på "AI Suggest Fields", så identifierar det automatiskt kolumner som titel, URL, score och author. Klicka på "Scrape" och exportera direkt till Excel, Google Sheets, Airtable eller Notion. Det hanterar paginering och kan till och med besöka undersidor för att hämta kommentardata. Ingen Python, inga selectors, inget underhåll.

Hur får jag historisk Hacker News-data?

är bästa verktyget för detta. Använd search_by_date-endpointen med numericFilters=created_at_i>TIMESTAMP för att filtrera på datumintervall. Du kan söka på nyckelord, filtrera på story-typ och bläddra igenom upp till 500 sidor med resultat. För större historiska analyser finns också publika dataset på (fullt arkiv), (28 miljoner poster) och (4 miljoner stories).

Läs mer

Innehållsförteckning

Testa Thunderbit

Skrapa leads och annan data med bara 2 klick. Drivet av AI.

Hämta Thunderbit Det är gratis
Extrahera data med AI
Överför enkelt data till Google Sheets, Airtable eller Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week