Sådan scraper jeg Hacker News med Python (2 metoder, fuld kode)

Sidst opdateret den April 16, 2026

For nogle måneder siden ville jeg lave et dagligt overblik over de største Hacker News-historier til vores team hos Thunderbit. Min første idé var bare at bogmærke siden og scrolle igennem den hver morgen. Det holdt i cirka tre dage, før jeg indså, at jeg brugte 20 minutter om dagen på bare at læse overskrifter og kopiere links ind i et regneark.

Hacker News er en af de mest værdifulde og koncentrerede kilder til teknologisk indsigt på internettet — omkring , cirka 1.300 nye historier hver dag og omkring 13.000 kommentarer dagligt. Uanset om du følger nye teknologitrends, overvåger dit brand, bygger en rekrutteringspipeline ud fra "Who's Hiring"-tråde eller bare vil holde dig opdateret på, hvad udviklermiljøet interesserer sig for, er manuel overvågning en tabt kamp.

Den gode nyhed: at scrape Hacker News med Python er overraskende ligetil. I denne guide gennemgår jeg to komplette metoder — HTML-scraping med BeautifulSoup og den officielle HN Firebase API — sammen med pagination, dataeksport, produktionsklare patterns og et no-code alternativ, når Python føles som overkill.

Hvorfor scrape Hacker News med Python?

Hacker News er ikke bare endnu en linkaggregator. Det er et kurateret, community-drevet feed, hvor de mest interessante tech-historier kommer til tops gennem upvotes og aktiv debat. Publikum hælder kraftigt mod teknologifolk (omkring ), og sitets 66 % direkte trafik viser, at det er et loyalt og vanebaseret publikum — ikke tilfældige besøgende.

Her er nogle grunde til, at folk scraper HN-data:

BrugsscenarieDet får du
Dagligt tech-overblikTophistorier, score og links leveret til din inbox eller Slack
Overvågning af brand/konkurrenterAlarmer når din virksomhed eller dit produkt nævnes
TrendanalyseFølg hvilke teknologier, sprog eller emner der får mere fart over tid
RekrutteringUdtræk jobopslag, tech stacks og lønsignaler fra "Who's Hiring"-tråde
IndholdsresearchFind emner med høj interesse, som du kan skrive om eller dele
SentimentanalyseMål communityets holdning til produkter, lanceringer eller brancheændringer

Virksomheder med en samlet værdi på over 400 milliarder dollars — Stripe, Dropbox og Airbnb — tilskriver Hacker News afgørende tidlig feedback og de første brugere. Drew Houston postede Dropbox-demoen på HN i april 2007, den ramte #1, og beta-waitlisten eksploderede fra 5.000 til 75.000 brugere på én dag. HN-data er ikke bare interessante — de er kommercielt værdifulde.

Dataene er offentligt tilgængelige, men sitets struktur gør manuel indsamling besværlig. Automatisering med Python er den praktiske løsning.

To måder at scrape Hacker News med Python: Overblik

Denne guide dækker to komplette, kørbare metoder:

  1. HTML-scraping med requests + BeautifulSoup — hent den rå HTML fra news.ycombinator.com og parse den for at udtrække historiedata. God til at lære scraping-fundamentaler og til at hente præcis det, der står på siden.
  2. Den officielle Hacker News Firebase API — kald JSON-endpoints direkte, uden behov for HTML-parsing. Bedre til stabile datapipelines, adgang til kommentarer og historiske data.

Her er en sammenligning side om side, så du kan vælge det, der passer bedst til dine behov:

KriteriumHTML-scraping (requests + BS4)HN Firebase APIThunderbit (No-code)
OpsætningskompleksitetMellem (parse HTML-selectors)Lav (JSON-endpoints)Ingen (2-klik Chrome-udvidelse)
DataaktualitetRealtid på forsidenRealtid (ethvert item via ID)Realtid
Risiko for rate limitMellem (robots.txt siger 30 sek. crawl delay)Lav (officiel, generøs)Håndteres af Thunderbit
Adgang til kommentarerSvær (nestet HTML)Nem (rekursiv via item IDs)Subside-scraping-funktion
Historiske dataBegrænsetVia Algolia Search APIN/A
Bedst tilLære scraping-fundamentalerPålidelige datapipelinesIkke-udviklere, hurtig eksport

Begge metoder inkluderer fuld, kørbar Python-kode. Og hvis du bare vil have dataene uden at skrive nogen kode, gennemgår jeg også det.

Før du går i gang

  • Sværhedsgrad: Begynder til øvet
  • Tidsforbrug: Ca. 15–20 minutter pr. metode
  • Du skal bruge:
    • Python 3.11+ installeret
    • En terminal eller kodeeditor
    • Chrome-browser (hvis du vil inspicere HN's HTML eller prøve no-code-løsningen)
    • (valgfrit, til no-code-metoden)

scrape-hacker-news-methods.webp

Opsætning af dit Python-miljø

Før vi rører HN-data, så lad os få miljøet klar. Jeg anbefaler at oprette et virtuelt miljø, så projektets afhængigheder holdes pæne og adskilte.

1# Opret og aktivér et virtuelt miljø
2python3 -m venv hn-scraper
3# macOS/Linux:
4source hn-scraper/bin/activate
5# Windows:
6hn-scraper\Scripts\activate
7# Installer de pakker, vi skal bruge til begge metoder
8pip install requests==2.33.1 beautifulsoup4==4.14.3 pandas==3.0.2 openpyxl==3.1.5

Til produktionsmønstre senere (cache, retries) får du også brug for:

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

Ingen særlige API-nøgler, ingen autentificeringstokens. HN's data er åbne.

Metode 1: Scrape Hacker News med Python ved hjælp af BeautifulSoup

Det er den klassiske tilgang — hent HTML'en, parse den og udtræk de data, du vil have. Det er sådan, de fleste lærer web scraping, og HN's enkle tabelbaserede layout gør det til et godt øvelsesområde.

Trin 1: Hent Hacker News-forsiden

Åbn din editor og opret en fil med navnet scrape_hn_bs4.py. Her er 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}, sidelængde: {len(response.text)} tegn")

Kør det. Du bør se Status: 200 og en sidelængde på omkring 40.000–50.000 tegn. Det er den rå HTML fra HN's forside, klar til at blive parsed.

Trin 2: Forstå HTML-strukturen

HN bruger et tabelbaseret layout — ingen moderne CSS grid eller flexbox. Hver historie på siden består af to centrale <tr>-rækker:

  • Historierækken (<tr class="athing submission">): indeholder placering, titel og link
  • Metadatarækken (den næste <tr>): indeholder points, forfatter, tidspunkt og antal kommentarer

De vigtigste selectors:

  • span.titleline > a — historiens titel og URL
  • span.score — stemmetal (fx "118 points")
  • a.hnuser — forfatterens brugernavn
  • span.age — tidspunktet for opslaget
  • Den sidste <a> i .subtext med "comment" i teksten — antal kommentarer

Hvis du højreklikker på en vilkårlig overskrift i Chrome og vælger "Inspect", vil du se noget i stil med dette:

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

Og metadatarækken nedenunder:

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>

Det er vigtigt at forstå disse selectors — hvis HN nogensinde ændrer deres markup, skal du opdatere dem. (Spoiler: API-metoden undgår helt det problem.)

Nu til det egentlige arbejde. Vi gennemløber hver historierække, henter titel og link fra historierækken og derefter score fra metadatarækken lige nedenunder.

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 og URL fra historierækken
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 fra den næste søskenderække
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# Filtrer historier med 50+ points, sorteret 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])

Et par bemærkninger til koden:

  • Walrus-operatoren (:=) virker i Python 3.8+. Den gør det muligt både at tildele og tjekke i samme linje — praktisk for valgfrie elementer som span.score, som ikke findes på alle rækker (fx har jobopslag ingen score).
  • HN bruger \xa0 (non-breaking space) mellem tallet og "comments", så vi splitter på det.
  • Historier, der linker til andre HN-sider (fx "Ask HN"-opslag), vil have relative URLs, der starter med item?id=. Du kan evt. tilføje https://news.ycombinator.com/ foran dem.

Trin 4: Kør det og se resultatet

Gem og kør:

1python scrape_hn_bs4.py

Du bør se output 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 er 30 historier fra side 1. Men HN har hundredvis af aktive historier på et givet tidspunkt. Vi dækker pagination i et senere afsnit.

Metode 2: Scrape Hacker News med Python ved hjælp af den officielle API

HN Firebase API er den officielt godkendte måde at tilgå Hacker News-data på. Ingen autentificering, ingen API-nøgler, ingen HTML-parsing. Du får rene JSON-svar. Jeg bruger denne metode til alt, der skal køre stabilt i produktion.

Vigtige API-endpoints, du skal kende

Base-URL'en er https://hacker-news.firebaseio.com/v0/. Her er de endpoints, der betyder noget:

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

Et story-item ser sådan ud:

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}

Feltet kids indeholder ID'er for direkte underkommentarer. Hver kommentar er selv et item, som igen kan have sine egne kids — sådan er kommentartreet bygget op.

Trin 1: Hent top story IDs

Opret en fil kaldet scrape_hn_api.py:

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

500 story IDs i én enkelt request — ingen parsing, ingen selectors, bare et JSON-array.

Trin 2: Hent story-detaljer via ID

Nu skal vi bruge de faktiske story-data. Her dukker fan-out-problemet op: 500 historier betyder 500 individuelle API-kald. I min benchmarking tog hver item-request cirka 1,2 sekunder sekventielt. For 500 historier er det omtrent 10 minutter.

For de fleste brugsscenarier har du ikke brug for alle 500. Her er kode til at hente top 30:

1def fetch_story(story_id):
2    """Hent detaljerne for en enkelt story fra HN API'et."""
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# Sortér efter score, vis top 10
7top = sorted(stories, key=lambda x: x["score"], reverse=True)[:10]
8pprint(top)

time.sleep(0.1) tilføjer en lille høflighedspause. Firebase API'et har ikke en angivet rate limit, men det er dårlig praksis at hamre løs på ethvert API uden pauser.

Trin 3: Scrape kommentarer (rekursiv træ-gennemgang)

Her skinner API'et virkelig i forhold til HTML-scraping. Kommentarer på HN er dybt nestede — svar på svar på svar. I HTML betyder det kompleks parsing af indlejrede tabeller. Med API'et giver hvert kommentarfelt kids IDs for dets børn, og så går du bare træet igennem rekursivt.

1def fetch_comments(item_id, depth=0, max_depth=3):
2    """Hent kommentarer rekursivt op til 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# Eksempel: hent kommentarer til den øverste story
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 til: {top_story['title']}")
18        all_comments = []
19        for kid_id in top_story_full["kids"][:5]:  # Første 5 topniveau-kommentarer
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 "[intet tekstindhold]"
25            print(f"{indent}[{c['author']}] {preview}...")

Denne rekursive tilgang er markant nemmere end at forsøge at parse nestede HTML-kommentartråde. Hvis du har brug for komplette kommentartæer, er API'et vejen frem.

Trin 4: Kør og se resultatet

1python scrape_hn_api.py

Du vil se strukturerede story-data efterfulgt af et nestet kommentar-preview. Dataene er renere, adgang til kommentarer er enkel, og der er ingen risiko for, at din scraper går i stykker, fordi HN ændrede et CSS-klassenavn.

Mere end side 1: Pagination og historiske data

De fleste HN-scraping-tutorials stopper ved side 1 — 30 historier. Det er fint til en hurtig demo, men rigtige use cases har ofte brug for mere dybde.

Scraping af flere sider med BeautifulSoup

HN's pagination bruger et simpelt URL-mønster: ?p=2, ?p=3 osv. Hver side returnerer 30 historier, og siden serverer op til omkring side 20 (cirka 600 historier i alt). Derefter får du tomme sider.

1import time
2def scrape_hn_pages(num_pages=5):
3    """Scrape flere sider af HN-forsiden."""
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"Side {page}: ingen historier fundet, stopper.")
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"Side {page}: scraped {len(story_rows)} historier")
23        # Respektér 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"\nSamlet antal scrape'de historier: {len(stories)}")

Det time.sleep(30) er vigtigt. HN's beder eksplicit om en crawl-delay på 30 sekunder. Ignorerer du det, risikerer du rate limiting (HTTP 429) eller midlertidig blokering. Fem sider med 30 sekunders mellemrum tager cirka 2,5 minutter — ikke øjeblikkeligt, men respektfuldt.

For brugere, der ikke vil administrere pagination-kode, håndterer automatisk pagination med klik og infinite scroll. Den klikker på "More"-knappen nederst på HN-sider uden nogen konfiguration.

Adgang til historiske Hacker News-data med Algolia API

Firebase API'et giver dig aktuelle data. Til historisk analyse — "Hvad var de største Python-historier i 2023?" eller "Hvordan har dækningen af AI ændret sig de seneste 5 år?" — har du brug for .

1import requests
2ALGOLIA_BASE = "https://hn.algolia.com/api/v1"
3> This paragraph contains content that cannot be parsed and has been skipped.
4# Eksempel: find Python-scraping-historier med 10+ points siden jan. 2024
5results = search_hn(
6    query="python scraping",
7    tags="story",
8)
9print(f"Fandt {results['nbHits']} resultater i alt")
10for hit in results["hits"][:5]:
11    print(f"  [{hit.get('points', 0)} pts] {hit['title']}")

Til datofiltrerede forespørgsler bruger du numericFilters:

1import calendar, datetime
2# Stories siden 1. januar 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'et er hurtigt (5–9 ms serverbehandlingstid), kræver ingen API-nøgle og understøtter pagination op til 500 sider. Til stor historisk analyse er det den bedste løsning.
7## Eksport af scrape'de Hacker News-data til CSV, Excel og Google Sheets
8Hver HN-scraping-guide, jeg har set, ender med `pprint()`-output i terminalen. Det er fint til debugging, men hvis du bygger et dagligt overblik eller laver trendanalyse, skal dataene i en fil. Her er, hvordan du gør.
9### Eksport til CSV med Python
10```python
11import csv
12def export_to_csv(stories, filename="hn_stories.csv"):
13    """Gem scrape'de historier i 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"Gemt {len(stories)} historier i {filename}")
20export_to_csv(stories)

Eksport til Excel med Python

1import pandas as pd
2def export_to_excel(stories, filename="hn_stories.xlsx"):
3    """Gem scrape'de historier i en Excel-fil."""
4    df = pd.DataFrame(stories)
5    df.to_excel(filename, index=False, engine="openpyxl")
6    print(f"Gemt {len(stories)} historier i {filename}")
7export_to_excel(stories)

Sørg for, at openpyxl er installeret — pandas bruger det som Excel-engine. Hvis det mangler, får du en ImportError.

Send til Google Sheets (valgfrit)

Til automatiserede workflows kan du måske sende data direkte til Google Sheets med biblioteket gspread. Det kræver opsætning af en Google Cloud service account (en engangsproces):

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

Det no-code alternativ til eksport

Hvis opsætning af service accounts og eksportkode lyder som mere arbejde end selve scrapingen, så forstår jeg det. Hos Thunderbit har vi bygget gratis dataeksport, så du kan sende scrape'de data direkte til Excel, Google Sheets, Airtable eller Notion — ingen kode, ingen credentials, ingen pipeline at vedligeholde. Til en enkelt dataudtræk er det oprigtigt hurtigere. Mere om det nedenfor.

Gør din scraper produktionsklar: fejlhåndtering, caching og planlægning

Hvis du bare kører en scraper én gang for sjov, er koden ovenfor fin. Hvis du kører den dagligt som led i en workflow, skal du have et par ting mere på plads.

Fejlhåndtering og retry-logik

Netværk fejler. Servere throttler. En enkelt dårlig request bør ikke få hele scrapen til at crashe. Her er en retry-funktion med eksponentiel 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    """Hent en URL med automatiske retries og eksponentiel backoff."""
6    response = requests.get(url, timeout=10)
7    response.raise_for_status()
8    return response
9# Brug:
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"Mislykkedes efter retries: {e}")

Biblioteket tenacity håndterer retry-logikken pænt. Det prøver op til 5 gange med jittered eksponentiel backoff — startende ved 1 sekund og op til 60 sekunder. Det håndterer HTTP 429 (rate limited), 503 (service unavailable) og midlertidige netværksfejl elegant.

Cache svar for at undgå at crawle igen og igen

Under udvikling kører du ofte din scraper mange gange, mens du finjusterer parsing-logikken. Uden cache rammer hver kørsel HN's servere igen for de samme data. Biblioteket requests-cache løser det med to linjer:

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

Når du har tilføjet de linjer øverst i dit script, bliver alle requests.get()-kald automatisk cached i en lokal SQLite-database. Kør scriptet 10 gange på en time, og kun den første kørsel rammer faktisk netværket. Det er et værktøj, , og med god grund.

Adskil crawling fra parsing

Et mønster erfarne scrapers sværger til: hent rådata først, parse dem bagefter. På den måde kan du rette en parsing-fejl og reparse uden at hente alt igen.

1import os, json
2def crawl_and_save(story_ids, output_dir="raw_data"):
3    """Hent story-data og gem 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  # Spring allerede hentede items over
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.
13Denne to-fasede tilgang er især værdifuld, når du scraper hundredvis af items og vil iterere hurtigt på, hvordan dataene behandles.
14### Automatisér din scraper efter en tidsplan
15Til et dagligt HN-overblik skal din scraper køre automatisk. To almindelige muligheder:
16**Mulighed 1: cron (Linux/Mac)**
17```bash
18# Kør hver dag kl. 08:30 UTC
1930 8 * * * /usr/bin/python3 /home/user/scrape_hn.py >> /home/user/scrape.log 2>&1

Mulighed 2: GitHub Actions (gratis, ingen server nødvendig)

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

Et par ting at være opmærksom på med GitHub Actions-planlægning: alle cron-tidspunkter er i UTC, forsinkelser på 15–60 minutter er normale (brug gerne tider som :30 i stedet for :00), og GitHub kan deaktivere planlagte workflows i repos uden aktivitet i 60 dage. Inkludér altid workflow_dispatch, så du kan trigge manuelt under test.

Som en enklere løsning lader Thunderbit's Scheduled Scraper-funktion dig beskrive planen med almindeligt sprog — noget i stil med "scrape hver morgen kl. 8" — uden server eller cron-opsætning.

Når Python er overkill: den no-code måde at scrape Hacker News på

Jeg vil være helt ærlig her, selvom jeg er Python-entusiast og mit team bygger udviklerværktøjer. Hvis du bare skal bruge dagens top 100 HN-historier i et regneark — lige nu, én gang — er det unødvendig overhead at skrive, debugge og køre et Python-script. Selve opsætningen (virtuelt miljø, installation af pakker, udregning af selectors) tager længere tid end dataindsamlingen.

Det er her passer ind. Sådan fungerer det:

  1. Åbn news.ycombinator.com i Chrome
  2. Klik på Thunderbit-ikonet, og vælg derefter "AI Suggest Fields"
  3. AI'en læser siden og foreslår kolonner som Titel, URL, Score, Forfatter og Antal kommentarer
  4. Tilpas felterne, hvis du vil (omdøb, fjern eller tilføj dine egne — du kan endda tilføje en AI-prompt som "Kategorisér som AI/DevTools/Web/Andet")
  5. Klik "Scrape" — data vises i en struktureret tabel
  6. Eksportér til Excel, Google Sheets, Airtable eller Notion

To klik til strukturerede data. Ingen selectors, ingen kode, ingen vedligeholdelse.

En reel fordel her: Thunderbit's AI tilpasser sig automatisk, når layoutet ændrer sig. Traditionelle scrapers med CSS-selectors går i stykker, når et site ændrer markup — og selvom HN's HTML er ret stabil, har den ændret sig (class="athing submission" blev opdateret, og span.titleline erstattede den ældre a.storylink). En AI-drevet scraper læser siden på ny hver gang, så den er ligeglad med ændringer i klassenavne.

python-vs-thunderbit-comparison.webp

Thunderbit håndterer også pagination (ved automatisk at klikke på HN's "More"-knap) og subside-scraping (ved at besøge hver histories kommentarside og hente diskussionsdata). Til brugsscenariet er det i praksis det samme som den rekursive API-kode i Metode 2 — bare uden at skrive en eneste linje.

Afvejningen er enkel: Python er det rigtige valg, når du har brug for custom logic, komplekse datatransformationer, automatiserede pipelines eller lærer at kode. Thunderbit er det rigtige valg, når du skal bruge data hurtigt, ikke vil vedligeholde kode, eller ikke er udvikler. Vælg det værktøj, der passer til din situation.

Python vs. API vs. No-code: Hvilken metode skal du vælge?

Her er det fulde beslutningsgrundlag:

KriteriumBeautifulSoup (HTML)Firebase APIAlgolia APIThunderbit (No-code)
Teknisk niveauØvet PythonBegynder PythonBegynder PythonIngen
Opsætningstid10–15 min5–10 min5–10 min2 min
VedligeholdelseMellem (selectors kan gå i stykker)Lav (stabil JSON)Lav (stabil JSON)Ingen
Dybde i dataKun forsideEthvert item, brugereSøgning + historikForside + subsider
KommentarerSværtNem (rekursiv)Nem (nestet træ)Subside-scraping
Historiske dataNejNejJa (fuldt arkiv)Nej
EksportmulighederKod selvKod selvKod selvIndbygget (Excel, Sheets osv.)
Planlægningcron / GitHub Actionscron / GitHub Actionscron / GitHub ActionsIndbygget scheduler
Bedst tilLæring af scrapingPålidelige pipelinesResearch og analyseHurtige dataudtræk

Hvis du lærer Python eller bygger noget skræddersyet, så vælg Metode 1 eller 2. Hvis du har brug for historisk analyse, så tilføj Algolia API'et. Hvis du bare vil have dataene uden koden, så .

Konklusion og vigtigste pointer

Her er, hvad du nu har i værktøjskassen:

  • To komplette Python-metoder til at scrape Hacker News — BeautifulSoup til HTML-parsing og Firebase API'et til rene JSON-data
  • Pagination-teknikker til at scrape længere end side 1, inklusive Algolia API'et til historiske data tilbage til 2007
  • Eksportkode til CSV, Excel og Google Sheets — fordi data i en terminal ikke er særlig nyttige for resten af teamet
  • Produktionsmønstre — retry-logik, caching, adskillelse af crawl og parsing samt planlagt automatisering via cron eller GitHub Actions
  • Et no-code alternativ når Python er mere værktøj, end du egentlig har brug for

Min anbefaling: Start med Firebase API'et (Metode 2) til de fleste brugsscenarier. Det er renere, mere pålideligt og giver adgang til kommentarer uden hovedpine med at parse nestet HTML. Tilføj Algolia API'et, når du har brug for historiske data. Og gem som bogmærke til de gange, hvor du bare skal bruge et hurtigt regneark og ikke gider sætte et helt Python-projekt op.

Hvis du vil dykke dybere, kan du prøve at scrape HN-kommentarer til , bygge en daglig digest-pipeline med GitHub Actions eller udforske Algolia API'et for at se, hvordan teknologitrends har ændret sig over det seneste årti.

Prøv Thunderbit til hurtig Hacker News-scraping

Ofte stillede spørgsmål

Er det lovligt at scrape Hacker News?

HN's data er offentligt tilgængelige, og Y Combinator stiller en officiel API til rådighed netop til programmatisk adgang. Sidens tillader scraping af read-only-indhold (forside, itemsider, brugersider), men beder om en crawl-delay på 30 sekunder. Respekter forsinkelsen, scrape ikke interaktive endpoints (stemmer, login), og du er på sikker grund. For mere om scraping-etisk, se vores guide om .

Har Hacker News en officiel API?

Ja. hacker-news.firebaseio.com/v0/ er gratis, kræver ingen autentificering og giver adgang til stories, kommentarer, brugerprofiler og alle feed-typer (top, new, best, ask, show, jobs). Den returnerer ren JSON og har ingen angivet rate limit, selvom det altid er en god idé at være hensynsfuld med request-frekvensen.

Hvordan scraper jeg Hacker News-kommentarer med Python?

Brug Firebase API'et og hent en story-item for at få dens kids-felt (et array af IDs for topniveau-kommentarer). Hver kommentar er selv et item med sit eget kids-felt til svar. Gå træet igennem rekursivt med en funktion, der henter hver kommentar og dens børn. Se afsnittet "Scrape kommentarer (rekursiv træ-gennemgang)" ovenfor for fuld kode. Alternativt returnerer hele det nestede kommentartre i én request — meget hurtigere til historier med mange kommentarer.

Kan jeg scrape Hacker News uden at skrive kode?

Ja. fungerer som en Chrome-udvidelse — åbn HN, klik på "AI Suggest Fields", og den identificerer automatisk kolonner som titel, URL, score og forfatter. Klik "Scrape" og eksportér direkte til Excel, Google Sheets, Airtable eller Notion. Den håndterer pagination og kan endda besøge undersider for at hente kommentar-data. Ingen Python, ingen selectors, ingen vedligeholdelse.

Hvordan får jeg historiske Hacker News-data?

er det bedste værktøj til det. Brug search_by_date-endpointet med numericFilters=created_at_i>TIMESTAMP for at filtrere efter datointerval. Du kan søge på nøgleord, filtrere på story-type og paginere gennem op til 500 sider med resultater. Til stor historisk analyse findes der også offentlige datasæt på (fuldt arkiv), (28 millioner poster) og (4 millioner historier).

Læs mere

Indholdsfortegnelse

Prøv Thunderbit

Hent leads og andre data med kun 2 klik. Drevet af AI.

Hent Thunderbit Det er gratis
Udtræk data med AI
Overfør nemt data til Google Sheets, Airtable eller Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week