Slik scraper jeg Hacker News med Python (2 metoder, komplett kode)

Sist oppdatert April 16, 2026

For noen måneder siden ville jeg lage en daglig oversikt over de viktigste Hacker News-artiklene for teamet vårt i Thunderbit. Den første tanken min var bare å bokmerke siden og skrolle gjennom den hver morgen. Det holdt i omtrent tre dager, før jeg skjønte at jeg brukte 20 minutter om dagen på å lese overskrifter og kopiere lenker inn i et regneark.

Hacker News er en av de mest verdifulle og konsentrerte kildene til teknologiinformasjon på internett — rundt , cirka 1 300 nye innlegg hver dag og om lag 13 000 kommentarer daglig. Enten du følger nye teknologitrender, overvåker merkevaren din, bygger en rekrutteringspipeline fra «Who's Hiring»-tråder, eller bare prøver å holde deg oppdatert på hva utviklermiljøet bryr seg om, blir det en tapt kamp å følge med manuelt.

Den gode nyheten er at det er overraskende enkelt å scrape Hacker News med Python, og i denne guiden viser jeg deg to komplette metoder — HTML-scraping med BeautifulSoup og den offisielle HN Firebase API-en — sammen med paginering, dataeksport, produksjonsklare mønstre og en no-code-snarvei for når Python føles som overkill.

Hvorfor scrape Hacker News med Python?

Hacker News er ikke bare enda en lenkeaggregator. Det er en kuratert, fellesskapsdrevet feed der de mest interessante teknologihistoriene løftes fram gjennom oppstemmer og aktiv diskusjon. Publikum består i stor grad av teknologifolk (omtrent ), og nettstedets 66 % direkte trafikk viser at dette er en lojal, vaneorientert leserskare — ikke tilfeldige besøkende.

Her er noen grunner til at folk scraper HN-data:

BruksområdeHva du får
Daglige teknologinyheterToppartikler, poeng og lenker sendt til innboksen eller Slack
Overvåking av merkevare/konkurrenterVarsler når firmaet eller produktet ditt blir nevnt
TrendanalyseFølg hvilke teknologier, språk eller temaer som får mer oppmerksomhet over tid
RekrutteringPlukk ut stillingsannonser, tech stack og lønnssignaler fra «Who's Hiring»-tråder
InnholdsresearchFinn temaer som gjør det bra og skriv eller del innhold rundt dem
SentimentanalyseMål hva fellesskapet mener om produkter, lanseringer eller endringer i bransjen

Selskaper med en samlet verdi på over 400 milliarder dollar — Stripe, Dropbox, Airbnb — tilskriver Hacker News viktig tidlig tilbakemelding og brukere. Drew Houston la ut Dropbox-demoen på HN i april 2007, den nådde #1, og betaversjonslisten eksploderte fra 5 000 til 75 000 brukere på én dag. HN-data er ikke bare interessante — de har også kommersiell verdi.

Dataene er offentlig tilgjengelige, men strukturen på nettstedet gjør manuell innsamling tungvint. Automatisering med Python er den praktiske løsningen.

To måter å scrape Hacker News med Python: oversikt

Denne guiden dekker to komplette, kjørbare tilnærminger:

  1. HTML-scraping med requests + BeautifulSoup — henter rå HTML fra news.ycombinator.com og parser den for å trekke ut historiedata. Flott for å lære grunnleggende scraping og hente akkurat det som ligger på siden.
  2. Den offisielle Hacker News Firebase API-en — leser JSON-endepunkter direkte, uten behov for HTML-parsing. Bedre for pålitelige datapipelines, kommentarer og historiske data.

Her er en side-ved-side-sammenligning som hjelper deg å velge det som passer best:

KriteriumHTML-scraping (requests + BS4)HN Firebase APIThunderbit (no-code)
OppsettkompleksitetMiddels (HTML-selektorer må parses)Lav (JSON-endepunkter)Ingen (2-klikk Chrome-utvidelse)
DatanyhetSanntid på forsidenSanntid (valgfri item etter ID)Sanntid
Risiko for rate limitMiddels (robots.txt sier 30 s crawl-delay)Lav (offisiell, generøs)Håndteres av Thunderbit
Tilgang til kommentarerVanskelig (nestet HTML)Enkelt (rekursiv gjennomgang av item-ID-er)Scraping av undersider
Historiske dataBegrensetVia Algolia Search APIIkke relevant
Best forLære scraping-grunnprinsipperPålitelige datapipelinesIkke-utviklere, raske eksportjobber

Begge metodene inkluderer full, kjørbar Python-kode. Og hvis du bare vil ha dataene uten å skrive noe kode i det hele tatt, går jeg også gjennom det.

Før du starter

  • Vanskelighetsgrad: Nybegynner til middels
  • Tidsbruk: Ca. 15–20 minutter per metode
  • Dette trenger du:
    • Python 3.11+ installert
    • En terminal eller kodeeditor
    • Chrome-nettleser (hvis du vil inspisere HN sin HTML eller teste no-code-alternativet)
    • (valgfritt, for no-code-metoden)

scrape-hacker-news-methods.webp

Slik setter du opp Python-miljøet

Før vi går løs på HN-dataene, la oss rydde opp i miljøet først. Jeg anbefaler å opprette et virtuelt miljø, så prosjektavhengighetene holder seg ryddige.

1# Opprett og aktiver et virtuelt miljø
2python3 -m venv hn-scraper
3# macOS/Linux:
4source hn-scraper/bin/activate
5# Windows:
6hn-scraper\Scripts\activate
7# Installer pakkene vi trenger for begge metodene
8pip install requests==2.33.1 beautifulsoup4==4.14.3 pandas==3.0.2 openpyxl==3.1.5

For produksjonsmønstre senere (cache og retry) trenger du også:

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

Ingen spesielle API-nøkler, ingen autentiseringstokener. HN-dataene er åpne.

Metode 1: Scrape Hacker News med Python ved hjelp av BeautifulSoup

Dette er den klassiske tilnærmingen — hent HTML-en, parser den og plukk ut dataene du trenger. Det er slik de fleste lærer web scraping, og HNs enkle tabellbaserte layout gjør siden til et godt øvingsfelt.

Steg 1: Hent forsiden til Hacker News

Åpne editoren din og opprett en fil som heter 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}, Sidestørrelse: {len(response.text)} tegn")

Kjør den. Du bør se Status: 200 og en sidelengde på rundt 40 000–50 000 tegn. Det er den rå HTML-en fra HNs forside, klar til å parses.

Steg 2: Forstå HTML-strukturen

HN bruker en tabellbasert layout — ingen moderne CSS grid eller flexbox. Hver historie på siden består av to viktige <tr>-rader:

  • Historieraden (<tr class="athing submission">): inneholder plassering, tittel og lenke
  • Metadata-raden (den neste <tr>): inneholder poeng, forfatter, tidspunkt og antall kommentarer

De viktigste selektorene:

  • span.titleline > a — tittelen og URL-en til historien
  • span.score — stemmeantallet (for eksempel «118 points»)
  • a.hnuser — brukernavnet til forfatteren
  • span.age — når innlegget ble publisert
  • Den siste <a> i .subtext med ordet «comment» i teksten — antall kommentarer

Hvis du høyreklikker på en hvilken som helst historietittel i Chrome og velger «Inspect», ser du noe slikt:

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

Og metadata-raden under:

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 avgjørende å forstå disse selektorene — hvis HN noen gang endrer markupen sin, må du oppdatere dem. (Spoiler: API-metoden slipper dette problemet helt.)

Steg 3: Trekk ut titler, lenker og poeng

Nå kommer selve jobben. Vi går gjennom hver historiesrad, henter tittel og lenke fra historieraden, og plukker deretter poeng fra metadata-raden rett 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    # Tittel og URL fra historieraden
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 neste 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# Filtrer til historier med 50+ poeng, sortert etter 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])

Noen korte kommentarer til koden:

  • Walrus-operatoren (:=) fungerer i Python 3.8+. Den lar oss tildele og sjekke samtidig — praktisk for valgfrie elementer som span.score, som ikke finnes på alle rader (for eksempel har jobbinnlegg ingen score).
  • HN bruker \xa0 (ikke-brytende mellomrom) mellom tallet og ordet «comments», så vi splitter på det.
  • Historier som lenker til andre HN-sider (som «Ask HN»-innlegg) har relative URL-er som starter med item?id=. Du vil kanskje legge til https://news.ycombinator.com/ foran disse.

Steg 4: Kjør og se resultatet

Lagre og kjør:

1python scrape_hn_bs4.py

Du bør se et resultat som dette:

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 hundrevis av aktive historier til enhver tid. Vi kommer tilbake til paginering i en senere del.

Metode 2: Scrape Hacker News med Python ved hjelp av den offisielle API-en

HN Firebase API er den offisielle og godkjente måten å hente data fra Hacker News på. Ingen autentisering, ingen API-nøkler, ingen HTML-parsing. Du får rene JSON-svar. Jeg bruker denne metoden for alt som må kjøre stabilt i produksjon.

Viktige API-endepunkter du bør kjenne til

Base-URL-en er https://hacker-news.firebaseio.com/v0/. Her er endepunktene som betyr noe:

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

Et story-item ser slik ut:

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 inneholder ID-ene til de direkte underkommentarene. Hver kommentar er selv et item som kan ha egne kids — slik er kommentar-treet bygget opp.

Steg 1: Hent ID-er for topphistorier

Opprett 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# Hent ID-er for topphistorier
6response = requests.get(f"{API_BASE}/topstories.json")
7story_ids = response.json()
8print(f"Fant {len(story_ids)} ID-er for topphistorier")
9# Output: Fant 500 ID-er for topphistorier

500 historie-ID-er i én forespørsel — ingen parsing, ingen selektorer, bare et JSON-array.

Steg 2: Hent historiedetaljer per ID

Nå trenger vi selve historiedataene. Her dukker fan-out-problemet opp: 500 historier betyr 500 separate API-kall. I min måling tar hvert item-kall omtrent 1,2 sekunder sekvensielt. For 500 historier blir det rundt 10 minutter.

For de fleste bruksområder trenger du ikke alle 500. Her er kode for å hente de 30 øverste:

1def fetch_story(story_id):
2    """Hent detaljene for én historie fra 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# Sorter etter score, vis topp 10
7top = sorted(stories, key=lambda x: x["score"], reverse=True)[:10]
8pprint(top)

time.sleep(0.1) legger inn en liten høflig pause. Firebase API-et har ikke en oppgitt rate limit, men det er dårlig praksis å hamre løs på et API uten pauser.

Steg 3: Scrape kommentarer (rekursiv tre-gjennomgang)

Det er her API-et virkelig skinner sammenlignet med HTML-scraping. Kommentarer på HN er dypt nestet — svar på svar på svar. I HTML betyr det at du må parse kompliserte, nestede tabellstrukturer. Med API-et får hver kommentar et kids-felt med ID-ene til barna sine, og du kan bare gå gjennom treet rekursivt.

1def fetch_comments(item_id, depth=0, max_depth=3):
2    """Hent kommentarer rekursivt opp 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 topphistorien
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 for: {top_story['title']}")
18        all_comments = []
19        for kid_id in top_story_full["kids"][:5]:  # Første 5 toppnivå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 "[ingen tekst]"
25            print(f"{indent}[{c['author']}] {preview}...")

Denne rekursive tilnærmingen er betydelig enklere enn å prøve å parse nestede HTML-kommentartråder. Hvis du trenger komplette kommentartre, er API-et veien å gå.

Steg 4: Kjør og se resultatet

1python scrape_hn_api.py

Du vil se strukturert historiedata etterfulgt av et nestet kommentarglimt. Dataene er renere, kommentarene er enkle å hente, og du slipper risikoen for at scraperen din ryker fordi HN endret et CSS-klassenavn.

Gå videre enn side 1: paginering og historiske data

De fleste HN-scraping-guider stopper ved side 1 — 30 historier. Det er greit for en rask demo, men reelle bruksområder trenger ofte mer dybde.

Scrape flere sider med BeautifulSoup

HN bruker et enkelt URL-mønster for paginering: ?p=2, ?p=3, osv. Hver side returnerer 30 historier, og nettstedet serverer opptil omtrent side 20 (rundt 600 historier totalt). Etter det får du tomme sider.

1import time
2def scrape_hn_pages(num_pages=5):
3    """Scrape flere sider med historier fra 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}: fant ingen historier, 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}: hentet {len(story_rows)} historier")
23        # Respekter robots.txt sitt 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 antall historier hentet: {len(stories)}")

time.sleep(30) er viktig. HNs ber uttrykkelig om 30 sekunders crawl-delay. Ignorerer du det, kan du bli rate-limited (HTTP 429) eller midlertidig blokkert. Fem sider med 30 sekunders intervaller tar omtrent 2,5 minutter — ikke øyeblikkelig, men respektfullt.

For brukere som ikke vil håndtere pagineringskode selv, tar seg av klikkbasert paginering og infinite scroll automatisk. Den klikker «More»-knappen nederst på HN-sidene uten at du trenger å konfigurere noe.

Hent historiske Hacker News-data med Algolia API

Firebase API-et gir deg nåværende data. For historisk analyse — «Hva var de viktigste Python-artiklene i 2023?» eller «Hvordan har AI-dekningen endret seg de siste 5 årene?» — trenger 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# Eksempel: finn Python-scraping-historier med 10+ poeng siden januar 2024
5results = search_hn(
6    query="python scraping",
7    tags="story",
8)
9print(f"Fant {results['nbHits']} treff totalt")
10for hit in results["hits"][:5]:
11    print(f"  [{hit.get('points', 0)} poeng] {hit['title']}")

For datofiltrerte søk bruker du numericFilters:

1import calendar, datetime
2# Historier 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 raskt (59 ms serverbehandlingstid), krever ingen API-nøkkel og støtter paginering opptil 500 sider. For stor historisk analyse er det det beste alternativet.
7## Eksport av scraped Hacker News-data til CSV, Excel og Google Sheets
8Hver HN-scraping-guide jeg har sett, ender med `pprint()` i terminalen. Det er greit for feilsøking, men hvis du bygger en daglig oversikt eller gjør trendanalyse, trenger du dataene i en fil. Her er hvordan du får det til.
9### Eksporter til CSV med Python
10```python
11import csv
12def export_to_csv(stories, filename="hn_stories.csv"):
13    """Lagre scrape-de historier til 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"Laget {len(stories)} historier i {filename}")
20export_to_csv(stories)

Eksporter til Excel med Python

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

Sørg for at openpyxl er installert — pandas bruker den som Excel-motor. Hvis den mangler, får du en ImportError.

Send til Google Sheets (valgfritt)

For automatiserte arbeidsflyter kan det være nyttig å sende data direkte til Google Sheets med gspread-biblioteket. Dette krever oppsett av en Google Cloud service account (en engangsprosess):

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

No-code-alternativet for eksport

Hvis oppsett av service accounts og eksportkode føles som mer jobb enn selve scrapingen, skjønner jeg det. Hos Thunderbit bygde vi gratis dataeksport som lar deg sende data rett til Excel, Google Sheets, Airtable eller Notion — uten kode, uten credentials og uten en pipeline du må vedlikeholde. For en enkelt datauthenting er det faktisk raskere. Mer om det under.

Gjør scraperen produksjonsklar: feilhåndtering, caching og planlegging

Hvis du bare kjører en scraper én gang for moro skyld, er koden over helt fin. Hvis du kjører den daglig som del av en arbeidsflyt, trenger du et par ting til.

Feilhåndtering og retry-logikk

Nettverk feiler. Servere struper trafikk. Én dårlig forespørsel bør ikke velte hele scrapingen. Her er en retry-funksjon med eksponentiell 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 automatisk retry og eksponentiell backoff."""
6    response = requests.get(url, timeout=10)
7    response.raise_for_status()
8    return response
9# Bruk:
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"Feilet etter retries: {e}")

Biblioteket tenacity håndterer retry-logikken ryddig. Det prøver opptil 5 ganger med jitter-basert eksponentiell backoff — starter på 1 sekund og går opp til maks 60 sekunder. Dette håndterer HTTP 429 (rate limit), 503 (tjenesten er utilgjengelig) og midlertidige nettverksfeil på en god måte.

Cache svar for å slippe å crawl på nytt

Under utvikling kjører du scraperen mange ganger mens du justerer parserlogikken. Uten cache treffer hver kjøring HN-serverne på nytt for de samme dataene. Biblioteket requests-cache fikser dette med to linjer:

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

Etter at du har lagt disse linjene øverst i skriptet, blir alle requests.get()-kall automatisk cached i en lokal SQLite-database. Kjør skriptet 10 ganger i løpet av en time, og bare første kjøring går faktisk ut på nett. Dette er et verktøy , og med god grunn.

Skill crawling fra parsing

Et mønster erfarne scrapers sverger til: last ned rådata først, parse dem etterpå. Da kan du fikse parserfeil og parse på nytt uten å hente dataene igjen.

1import os, json
2def crawl_and_save(story_ids, output_dir="raw_data"):
3    """Hent historiedata og lagre 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  # Hopp over elementer som allerede er hentet
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 totrinnsmodellen er spesielt nyttig når du scraper hundrevis av elementer og vil iterere raskt på hvordan du behandler dataene.
14### Automatiser scraperen på en tidsplan
15For en daglig HN-oversikt må scraperen kjøre automatisk. To vanlige alternativer:
16**Alternativ 1: cron (Linux/Mac)**
17```bash
18# Kjør hver 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 nødvendig)

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

Noen fallgruver med planlegging i GitHub Actions: all cron-timing er i UTC, forsinkelser på 15–60 minutter er vanlige (bruk tider som :30 i stedet for :00), og GitHub kan deaktivere planlagte workflows i repos uten aktivitet i 60 dager. Inkluder alltid workflow_dispatch slik at du kan trigge manuelt under testing.

For et enklere alternativ kan Thunderbits Scheduled Scraper-funksjon la deg beskrive planen i vanlig språk — noe som «scrape hver morgen kl. 8» — uten server eller cron-oppsett.

Når Python er overkill: no-code-måten å scrape Hacker News på

Jeg skal være ærlig her, selv om jeg er Python-entusiast og teamet mitt bygger utviklerverktøy. Hvis du bare trenger dagens topp 100 HN-historier i et regneark — akkurat nå, én gang — er det unødvendig mye arbeid å skrive, feilsøke og kjøre et Python-skript. Bare oppsettet (virtuelt miljø, installasjon av pakker, finne selektorer) tar lenger tid enn selve datainnhentingen.

Det er her passer inn. Slik ser arbeidsflyten ut:

  1. Åpne news.ycombinator.com i Chrome
  2. Klikk på Thunderbit-utvidelsen, deretter «AI Suggest Fields»
  3. AI-en leser siden og foreslår kolonner: Title, URL, Score, Author, Comment Count, Time Posted
  4. Juster feltene om du vil (gi dem nytt navn, fjern noen eller legg til egne — du kan til og med legge inn en AI-prompt som «Kategoriser som AI/DevTools/Web/Other»)
  5. Klikk «Scrape» — dataene vises i en strukturert tabell
  6. Eksporter til Excel, Google Sheets, Airtable eller Notion

To klikk til strukturerte data. Ingen selektorer, ingen kode, ingen vedlikehold.

En reell fordel her er at Thunderbits AI tilpasser seg layoutendringer automatisk. Tradisjonelle scrapers som bruker CSS-selektorer ryker når et nettsted endrer markup — og selv om HNs HTML er ganske stabil, har den endret seg (klassen class="athing submission" ble oppdatert, og span.titleline erstattet den eldre a.storylink). En AI-drevet scraper leser siden på nytt hver gang, så den bryr seg ikke om klasseendringer.

python-vs-thunderbit-comparison.webp

Thunderbit håndterer også paginering (ved å klikke HNs «More»-knapp automatisk) og scraping av undersider (ved å besøke kommentarsiden til hver historie og hente inn diskusjonsdata). For brukstilfellet tilsvarer det den rekursive API-koden i Metode 2 — bare uten én eneste linje å skrive.

Avveiningene er ganske enkle: Python er riktig valg når du trenger egendefinert logikk, komplekse datatransformasjoner, planlagte automasjonsflyter eller vil lære å kode. Thunderbit er riktig valg når du trenger data raskt, ikke vil vedlikeholde kode, eller ikke er utvikler. Velg verktøyet som passer situasjonen din.

Python vs. API vs. no-code: hvilken metode bør du velge?

Her er hele beslutningsrammeverket:

KriteriumBeautifulSoup (HTML)Firebase APIAlgolia APIThunderbit (no-code)
Teknisk nivå som krevesMiddels PythonNybegynner-PythonNybegynner-PythonIngen
Oppsettstid10–15 min5–10 min5–10 min2 min
VedlikeholdsbyrdeMiddels (selektorer kan ryke)Lav (stabil JSON)Lav (stabil JSON)Ingen
Dybde i dataBare forsidenHvilket som helst item, brukereSøk + historikkForside + undersider
KommentarerVanskeligEnkelt (rekursivt)Enkelt (nestet tre)Scraping av undersider
Historiske dataNeiNeiJa (fullt arkiv)Nei
EksportalternativerDu koder det selvDu koder det selvDu koder det selvInnebygd (Excel, Sheets osv.)
Planleggingcron / GitHub Actionscron / GitHub Actionscron / GitHub ActionsInnebygd scheduler
Best forLære scrapingPålitelige pipelinesForskning og analyseRaske datauthentinger

Hvis du lærer Python eller bygger noe skreddersydd, velg Metode 1 eller 2. Hvis du trenger historisk analyse, legg til Algolia API-et. Hvis du bare vil ha dataene uten koden, .

Konklusjon og viktigste læringspunkter

Dette har du nå i verktøykassen:

  • To komplette Python-metoder for å scrape Hacker News — BeautifulSoup for HTML-parsing og Firebase API for rene JSON-data
  • Teknikker for paginering slik at du kan scrape mer enn side 1, inkludert Algolia API for historiske data tilbake til 2007
  • Eksportkode for CSV, Excel og Google Sheets — fordi data i terminalen ikke hjelper resten av teamet ditt
  • Produksjonsmønstre — retry-logikk, caching, deling mellom crawling og parsing, og planlagt automatisering via cron eller GitHub Actions
  • Et no-code-alternativ for når Python er mer verktøy enn du egentlig trenger

Min anbefaling er å starte med Firebase API-et (Metode 2) for de fleste bruksområder. Det er renere, mer pålitelig og gir deg tilgang til kommentarer uten bryet med å parse nestet HTML. Legg til Algolia API-et når du trenger historiske data. Og ha bokmerket for de gangene du bare trenger et raskt regneark og ikke vil starte et helt Python-prosjekt.

Hvis du vil gå dypere, kan du prøve å scrape HN-kommentarer for , bygge en daglig oversiktspipeline med GitHub Actions, eller utforske Algolia API-et for å se hvordan teknologitrender har endret seg det siste tiåret.

Prøv Thunderbit for rask scraping av Hacker News

Vanlige spørsmål

Er det lov å scrape Hacker News?

HN-dataene er offentlig tilgjengelige, og Y Combinator tilbyr en offisiell API nettopp for programmatisk tilgang. Nettstedets tillater scraping av skrivebeskyttet innhold (forside, itemsider, brukersider), men ber om 30 sekunders crawl-delay. Følg denne pausen, ikke scrape interaktive endepunkter (stemming, innlogging), så er du på trygg grunn. For mer om scraping og etikk, se guiden vår om .

Har Hacker News en offisiell API?

Ja. hacker-news.firebaseio.com/v0/ er gratis, krever ingen autentisering og gir tilgang til historier, kommentarer, brukerprofiler og alle feed-typer (top, new, best, ask, show, jobs). Den returnerer ren JSON og har ingen oppgitt rate limit, selv om det alltid anbefales å være hensynsfull med forespørsler.

Hvordan scraper jeg Hacker News-kommentarer med Python?

Ved hjelp av Firebase API-et henter du et story-item for å få kids-feltet (en array med ID-er til toppnivåkommentarer). Hver kommentar er selv et item med eget kids-felt for svar. Gå gjennom treet rekursivt med en funksjon som henter hver kommentar og barna dens. Se delen «Scrape kommentarer (rekursiv tre-gjennomgang)» over for komplett kode. Alternativt returnerer hele det nestede kommentartreet i én forespørsel — mye raskere for historier med mange kommentarer.

Kan jeg scrape Hacker News uten å skrive kode?

Ja. fungerer som en Chrome-utvidelse — åpne HN, klikk «AI Suggest Fields», og den identifiserer automatisk kolonner som tittel, URL, score og forfatter. Klikk «Scrape» og eksporter direkte til Excel, Google Sheets, Airtable eller Notion. Den håndterer paginering og kan til og med besøke undersider for å hente kommentar-data. Ingen Python, ingen selektorer, ingen vedlikehold.

Hvordan får jeg historiske Hacker News-data?

er det beste verktøyet for dette. Bruk search_by_date-endepunktet med numericFilters=created_at_i>TIMESTAMP for å filtrere på datointervall. Du kan søke med nøkkelord, filtrere på type historie og paginere gjennom opptil 500 sider med resultater. For større historiske analyser finnes det også offentlige datasett på (fullt arkiv), (28 millioner poster) og (4 millioner historier).

Les mer

Innholdsfortegnelse

Prøv Thunderbit

Hent leads og andre data med bare 2 klikk. Drevet av AI.

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