Vor ein paar Monaten wollte ich für unser Team bei Thunderbit einen täglichen Überblick über die wichtigsten Hacker-News-Storys aufsetzen. Mein erster Gedanke war, die Seite einfach zu bookmarken und mir jeden Morgen die Beiträge anzuschauen. Das hat ungefähr drei Tage funktioniert, bis mir klar wurde, dass ich jeden Tag rund 20 Minuten damit verbringe, Überschriften zu lesen und Links händisch in eine Tabelle zu kopieren.
Hacker News ist eine der ergiebigsten und zugleich am stärksten verdichteten Quellen für Tech-Intelligenz im Internet — mit rund , etwa 1.300 neu eingereichten Stories pro Tag und ungefähr 13.000 Kommentaren täglich. Egal ob du neue Tech-Trends verfolgen, deine Marke im Blick behalten, aus "Who's Hiring"-Threads einen Recruiting-Stream bauen oder einfach nah dran bleiben willst, was in der Entwicklerwelt gerade abgeht: Alles manuell mitzulesen ist ein Kampf, den man auf Dauer nicht gewinnt.
Die gute Nachricht: Hacker News mit Python zu scrapen ist überraschend einfach. In diesem Leitfaden zeige ich dir zwei vollständige Wege — HTML-Scraping mit BeautifulSoup und die offizielle HN Firebase API — inklusive Pagination, Datenexport, produktionsreifen Mustern und einem No-Code-Shortcut für den Fall, dass Python dir zu viel des Guten erscheint.
Warum Hacker News mit Python scrapen?
Hacker News ist nicht bloß ein weiterer Link-Aggregator. Es ist ein kuratierter, von der Community getriebener Feed, bei dem die spannendsten Tech-Storys durch Upvotes und lebhafte Diskussionen nach oben gespült werden. Die Zielgruppe ist stark technikaffin (etwa ), und die Direktzugriffsrate von 66 % zeigt: Hier liest eine treue Stammleserschaft mit — nicht zufällige Laufkundschaft.
Darum scrapen Menschen HN-Daten:
| Anwendungsfall | Was du bekommst |
|---|---|
| Tägliches Tech-Briefing | Top-Storys, Scores und Links direkt per E-Mail oder Slack |
| Marken- und Wettbewerbsmonitoring | Benachrichtigungen, wenn dein Unternehmen oder Produkt erwähnt wird |
| Trendanalyse | Verfolge, welche Technologien, Sprachen oder Themen im Zeitverlauf an Fahrt gewinnen |
| Recruiting | Analysiere "Who's Hiring"-Threads nach Stellenangeboten, Tech-Stacks und Gehaltsindikatoren |
| Content-Recherche | Finde Themen mit hoher Resonanz für neue Inhalte |
| Sentiment-Analyse | Ermittle die Stimmung der Community zu Produkten, Launches oder Branchenentwicklungen |
Unternehmen mit zusammen mehr als 400 Milliarden US-Dollar Marktkapitalisierung — darunter Stripe, Dropbox und Airbnb — haben Hacker News wichtige frühe Rückmeldungen und Nutzer zu verdanken. Drew Houston stellte im April 2007 die Dropbox-Demo auf HN ein, sie landete auf Platz 1, und die Beta-Warteliste sprang an einem einzigen Tag von 5.000 auf 75.000 Nutzer. HN-Daten sind also nicht nur spannend, sondern auch wirtschaftlich relevant.
Die Daten sind öffentlich verfügbar, aber die Struktur der Seite macht die manuelle Erfassung mühsam. Automatisierung mit Python ist hier die pragmatische Lösung.
Zwei Wege, Hacker News mit Python zu scrapen: Überblick
Dieser Leitfaden deckt zwei vollständige, direkt ausführbare Ansätze ab:
- HTML-Scraping mit
requests+ BeautifulSoup — lädt das rohe HTML von news.ycombinator.com und liest daraus die Story-Daten aus. Ideal, um die Grundlagen des Scrapings zu lernen und die Inhalte der Seite sehr genau zu erfassen. - Die offizielle Hacker News Firebase API — greift direkt auf JSON-Endpunkte zu, ganz ohne HTML-Parsing. Besser für robuste Datenpipelines, Kommentare und historische Daten.
Hier ein direkter Vergleich, damit du leichter entscheiden kannst, was zu deinem Bedarf passt:
| Kriterium | HTML-Scraping (requests + BS4) | HN Firebase API | Thunderbit (No-Code) |
|---|---|---|---|
| Einrichtungsaufwand | Mittel (HTML-Selektoren parsen) | Niedrig (JSON-Endpunkte) | Keiner (Chrome-Erweiterung in 2 Klicks) |
| Aktualität der Daten | Echtzeit-Startseite | Echtzeit (jedes Item per ID) | Echtzeit |
| Risiko durch Rate Limits | Mittel (robots.txt nennt 30 Sekunden Crawl-Delay) | Niedrig (offiziell, großzügig) | Von Thunderbit verwaltet |
| Zugriff auf Kommentare | Schwer (verschachteltes HTML) | Einfach (rekursive Item-IDs) | Subpage-Scraping-Funktion |
| Historische Daten | Begrenzt | Über die Algolia Search API | N/A |
| Am besten geeignet für | Scraping-Grundlagen lernen | Zuverlässige Datenpipelines | Nicht-Entwickler, schnelle Exporte |
Beide Methoden enthalten vollständigen, ausführbaren Python-Code. Und wenn du einfach nur die Daten willst, ohne überhaupt Code zu schreiben, zeige ich dir auch dafür eine Lösung.
Bevor du startest
- Schwierigkeitsgrad: Anfänger bis Fortgeschrittene
- Benötigte Zeit: ca. 15–20 Minuten pro Methode
- Was du brauchst:
- Python 3.11+ installiert
- Ein Terminal oder Code-Editor
- Chrome-Browser (wenn du HNs HTML ansehen oder die No-Code-Option ausprobieren möchtest)
- (optional, für die No-Code-Methode)

Python-Umgebung einrichten
Bevor wir uns an HN-Daten machen, richten wir die Umgebung ein. Ich empfehle eine virtuelle Umgebung, damit die Abhängigkeiten sauber getrennt bleiben.
1# Virtuelle Umgebung erstellen und aktivieren
2python3 -m venv hn-scraper
3# macOS/Linux:
4source hn-scraper/bin/activate
5# Windows:
6hn-scraper\Scripts\activate
7# Benötigte Pakete für beide Methoden installieren
8pip install requests==2.33.1 beautifulsoup4==4.14.3 pandas==3.0.2 openpyxl==3.1.5
Für die späteren Produktionsmuster (Caching, Retries) brauchst du außerdem:
1pip install requests-cache==1.3.1 tenacity==9.1.4
Keine API-Keys, keine Authentifizierungstokens. Die HN-Daten sind frei zugänglich.
Methode 1: Hacker News mit Python und BeautifulSoup scrapen
Das ist der klassische Weg — HTML abrufen, parsen und die gewünschten Daten herausziehen. So lernen die meisten Menschen Web Scraping, und das tabellenbasierte HN-Layout ist dafür ein gutes Übungsfeld.
Schritt 1: Die Hacker-News-Startseite abrufen
Öffne deinen Editor und erstelle eine Datei namens scrape_hn_bs4.py. Hier ist der Startcode:
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}, Seitenlänge: {len(response.text)} Zeichen")
Führe das Skript aus. Du solltest Status: 200 und eine Seitenlänge von ungefähr 40.000–50.000 Zeichen sehen. Das ist das rohe HTML der HN-Startseite, das nun im Speicher liegt und geparst werden kann.
Schritt 2: Die HTML-Struktur verstehen
HN nutzt ein tabellenbasiertes Layout — kein modernes CSS Grid oder Flexbox. Jede Story auf der Seite besteht aus zwei wichtigen <tr>-Zeilen:
- Die Story-Zeile (
<tr class="athing submission">): enthält Rang, Titel und Link - Die Metadaten-Zeile (die nächste
<tr>): enthält Punkte, Autor, Zeitpunkt und Kommentaranzahl
Die wichtigsten Selektoren:
span.titleline > a— Titel und URL der Storyspan.score— die Punktzahl (z. B. "118 points")a.hnuser— der Benutzername des Autorsspan.age— der Veröffentlichungszeitpunkt- Das letzte
<a>in.subtextmit "comment" im Text — die Kommentaranzahl
Wenn du in Chrome auf einen Story-Titel rechtsklickst und "Untersuchen" wählst, siehst du etwa Folgendes:
1<span class="titleline">
2 <a href="https://darkbloom.dev">Darkbloom – Private inference on idle Macs</a>
3</span>
Und darunter die Metadaten-Zeile:
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 comments</a>
Diese Selektoren zu verstehen ist entscheidend — wenn HN sein Markup ändert, musst du sie anpassen. (Spoiler: Die API-Methode umgeht dieses Problem komplett.)
Schritt 3: Titel, Links und Scores extrahieren
Jetzt kommt der eigentliche Teil. Wir gehen jede Story-Zeile durch, holen Titel und Link aus der Story-Zeile und lesen dann den Score aus der direkt darunterliegenden Metadaten-Zeile aus.
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 und URL aus der Story-Zeile
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 # Metadaten aus der nächsten Zeile
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# Stories mit 50+ Punkten filtern und nach Score sortieren
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])
Ein paar Hinweise zum Code:
- Der Walrus-Operator (
:=) funktioniert ab Python 3.8. Damit kannst du zuweisen und prüfen zugleich — praktisch für optionale Elemente wiespan.score, die nicht in jeder Zeile existieren (z. B. bei Job-Posts ohne Punkte). - HN verwendet
\xa0(geschütztes Leerzeichen) zwischen Zahl und "comments", deshalb teilen wir an dieser Stelle. - Stories, die auf andere HN-Seiten verlinken (z. B. "Ask HN"-Beiträge), haben relative URLs, die mit
item?id=beginnen. Dafür kannst du bei Bedarfhttps://news.ycombinator.com/voranstellen.
Schritt 4: Ausführen und Ergebnisse ansehen
Speichere und führe aus:
1python scrape_hn_bs4.py
Du solltest eine Ausgabe wie diese sehen:
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 ...]
Das sind 30 Stories von Seite 1. Hacker News hat aber zu jedem Zeitpunkt Hunderte aktive Stories. Pagination behandeln wir weiter unten.
Methode 2: Hacker News mit Python über die offizielle API scrapen
Die HN Firebase API ist der offiziell unterstützte Weg, um auf Hacker-News-Daten zuzugreifen. Keine Authentifizierung, keine API-Keys, kein HTML-Parsing. Du erhältst saubere JSON-Antworten. Ich nutze diese Methode immer dann, wenn etwas zuverlässig in Produktion laufen muss.
Wichtige API-Endpunkte, die du kennen solltest
Die Basis-URL lautet https://hacker-news.firebaseio.com/v0/. Diese Endpunkte sind relevant:
This paragraph contains content that cannot be parsed and has been skipped.
Ein Story-Objekt sieht so aus:
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}
Das Feld kids enthält die IDs der direkten Unterkommentare. Jeder Kommentar ist wiederum ein eigenes Item, das ebenfalls kids haben kann — so ist der Kommentarbaum aufgebaut.
Schritt 1: Top-Story-IDs abrufen
Erstelle eine Datei namens scrape_hn_api.py:
1import requests
2import time
3from pprint import pprint
4API_BASE = "https://hacker-news.firebaseio.com/v0"
5# Top-Story-IDs abrufen
6response = requests.get(f"{API_BASE}/topstories.json")
7story_ids = response.json()
8print(f"{len(story_ids)} Top-Story-IDs erhalten")
9# Ausgabe: 500 Top-Story-IDs
500 Story-IDs in einer einzigen Anfrage — kein Parsen, keine Selektoren, nur ein JSON-Array.
Schritt 2: Story-Details per ID abrufen
Jetzt brauchen wir die eigentlichen Story-Daten. Hier zeigt sich das Fan-out-Problem: 500 Stories bedeuten 500 einzelne API-Aufrufe. In meinen Tests dauert jede Item-Anfrage nacheinander ungefähr 1,2 Sekunden. Bei 500 Stories sind das rund 10 Minuten.
Für die meisten Anwendungsfälle brauchst du ohnehin nicht alle 500. Hier ist Code, der die Top 30 holt:
1def fetch_story(story_id):
2 """Ruft die Details einer einzelnen Story über die HN-API ab."""
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# Nach Score sortieren, Top 10 anzeigen
7top = sorted(stories, key=lambda x: x["score"], reverse=True)[:10]
8pprint(top)
time.sleep(0.1) sorgt für eine kleine Pause. Die Firebase API nennt zwar kein explizites Rate Limit, aber jede API ohne Pausen zu belasten ist keine gute Praxis.
Schritt 3: Kommentare scrapen (rekursiver Baumdurchlauf)
Hier spielt die API ihren größten Vorteil gegenüber HTML-Scraping aus. Kommentare auf HN sind tief verschachtelt — Antworten auf Antworten auf Antworten. Im HTML bedeutet das, komplexe verschachtelte Tabellen zu parsen. Über die API liefert das kids-Feld jeder Kommentar-ID einfach die Kind-IDs, und du läufst rekursiv durch den Baum.
1def fetch_comments(item_id, depth=0, max_depth=3):
2 """Ruft Kommentare rekursiv bis max_depth ab."""
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# Beispiel: Kommentare für die Top-Story abrufen
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"\nKommentare zu: {top_story['title']}")
18 all_comments = []
19 for kid_id in top_story_full["kids"][:5]: # Erste 5 Top-Level-Kommentare
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 "[kein Text]"
25 print(f"{indent}[{c['author']}] {preview}...")
Dieser rekursive Ansatz ist deutlich einfacher, als verschachtelte Kommentar-Threads im HTML zu parsen. Wenn du vollständige Kommentarbäume brauchst, ist die API der richtige Weg.
Schritt 4: Ausführen und Ergebnisse ansehen
1python scrape_hn_api.py
Du siehst strukturierte Story-Daten und darunter eine verschachtelte Kommentarvorschau. Die Daten sind sauberer, der Kommentarzugriff ist trivial, und du läufst nicht Gefahr, dass dein Scraper scheitert, nur weil HN eine CSS-Klasse umbenannt hat.
Mehr als nur Seite 1: Pagination und historische Daten
Die meisten HN-Scraping-Tutorials hören nach Seite 1 auf — also nach 30 Stories. Für einen schnellen Demo-Case reicht das, aber echte Anwendungsfälle brauchen oft mehr Tiefe.
Mehrere Seiten mit BeautifulSoup scrapen
Die Pagination von HN nutzt ein einfaches URL-Muster: ?p=2, ?p=3 usw. Jede Seite liefert 30 Stories, und die Seite stellt ungefähr bis Seite 20 Inhalte bereit (insgesamt rund 600 Stories). Danach kommen leere Seiten.
1import time
2def scrape_hn_pages(num_pages=5):
3 """Mehrere Seiten der HN-Startseite scrapen."""
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"Seite {page}: keine Stories gefunden, Abbruch.")
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"Seite {page}: {len(story_rows)} Stories gescraped")
23 # robots.txt-Crawl-Delay von 30 Sekunden respektieren
24 if page < num_pages:
25 time.sleep(30)
26 return all_stories
27stories = scrape_hn_pages(5)
28print(f"\nInsgesamt gescrapete Stories: {len(stories)}")
time.sleep(30) ist wichtig. HNs verlangt ausdrücklich ein Crawl-Delay von 30 Sekunden. Wer das ignoriert, riskiert Rate Limits (HTTP 429) oder eine vorübergehende Sperre. Fünf Seiten mit 30-Sekunden-Abständen dauern also etwa 2,5 Minuten — nicht blitzschnell, aber fair.
Wer die Pagination nicht selbst programmieren will, kann mit klickbasierte und Infinite-Scroll-Pagination automatisch verarbeiten. Das Tool klickt den "More"-Button am Seitenende ohne jede Konfiguration.
Historische Hacker-News-Daten mit der Algolia API abrufen
Die Firebase API liefert aktuelle Daten. Für historische Analysen — "Welche Python-Storys waren 2023 am wichtigsten?" oder "Wie hat sich die AI-Berichterstattung in den letzten 5 Jahren verändert?" — brauchst du die .
1import requests
2ALGOLIA_BASE = "https://hn.algolia.com/api/v1"
3> This paragraph contains content that cannot be parsed and has been skipped.
4# Beispiel: Python-Scraping-Stories mit 10+ Punkten seit Januar 2024 finden
5results = search_hn(
6 query="python scraping",
7 tags="story",
8)
9print(f"Insgesamt {results['nbHits']} Ergebnisse gefunden")
10for hit in results["hits"][:5]:
11 print(f" [{hit.get('points', 0)} Pkt.] {hit['title']}")
Für datumsbasierte Filter nutze numericFilters:
1import calendar, datetime
2# Stories seit dem 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.
6Die Algolia API ist schnell (5–9 ms Server-Verarbeitungszeit), braucht keinen API-Key und unterstützt Pagination bis zu 500 Seiten. Für umfangreiche historische Analysen ist sie die beste verfügbare Option.
7## Gescrapete Hacker-News-Daten nach CSV, Excel und Google Sheets exportieren
8Jedes HN-Scraping-Tutorial, das ich gesehen habe, endet mit `pprint()`-Ausgabe im Terminal. Zum Debuggen ist das okay, aber wenn du einen täglichen Digest baust oder Trends analysierst, brauchst du die Daten in einer Datei. So bekommst du sie dorthin.
9### Export nach CSV mit Python
10```python
11import csv
12def export_to_csv(stories, filename="hn_stories.csv"):
13 """Gescrapte Stories in eine CSV-Datei schreiben."""
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"{len(stories)} Stories in {filename} gespeichert")
20export_to_csv(stories)
Export nach Excel mit Python
1import pandas as pd
2def export_to_excel(stories, filename="hn_stories.xlsx"):
3 """Gescrapte Stories in eine Excel-Datei schreiben."""
4 df = pd.DataFrame(stories)
5 df.to_excel(filename, index=False, engine="openpyxl")
6 print(f"{len(stories)} Stories in {filename} gespeichert")
7export_to_excel(stories)
Stelle sicher, dass openpyxl installiert ist — pandas nutzt es als Excel-Engine. Fehlt es, bekommst du einen ImportError.
Optional: In Google Sheets übertragen
Für automatisierte Workflows möchtest du die Daten vielleicht direkt mit der gspread-Bibliothek in Google Sheets schreiben. Dafür musst du einmalig einen Google-Cloud-Service-Account einrichten:
1import gspread
2gc = gspread.service_account(filename="service_account.json")
3sh = gc.open("HN Daily Digest")
4worksheet = sh.sheet1
5# Stories in Zeilen umwandeln
6header = list(stories[0].keys())
7rows = [list(s.values()) for s in stories]
8worksheet.clear()
9worksheet.update([header] + rows)
10print("In Google Sheets übertragen")
Die No-Code-Export-Alternative
Wenn das Einrichten von Service Accounts und Export-Code mehr Aufwand klingt als das eigentliche Scraping, kann ich das gut nachvollziehen. Bei Thunderbit haben wir einen kostenlosen Datenexport entwickelt, mit dem du gescrapte Daten direkt nach Excel, Google Sheets, Airtable oder Notion schicken kannst — ohne Code, ohne Zugangsdaten, ohne Wartungsaufwand. Für einen einmaligen Datenabruf ist das tatsächlich schneller. Mehr dazu weiter unten.
Deinen Scraper produktionsreif machen: Fehlerbehandlung, Caching und Scheduling
Wenn du ein Skript nur einmal zum Spaß laufen lässt, reicht der Code oben völlig aus. Wenn es aber täglich Teil eines Workflows sein soll, brauchst du noch ein paar Bausteine.
Fehlerbehandlung und Retry-Logik
Netzwerke fallen aus. Server drosseln Anfragen. Eine einzelne fehlerhafte Anfrage sollte nicht deinen gesamten Scrape zu Fall bringen. Hier ist eine Retry-Funktion mit exponentiellem 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 """Lädt eine URL mit automatischen Retries und exponentiellem Backoff."""
6 response = requests.get(url, timeout=10)
7 response.raise_for_status()
8 return response
9# Verwendung:
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"Nach Retries fehlgeschlagen: {e}")
Die Bibliothek tenacity übernimmt die Retry-Logik sauber. Sie versucht es bis zu 5-mal mit zufälligem exponentiellem Backoff — beginnend bei 1 Sekunde, maximal 60 Sekunden. Das hilft bei HTTP 429 (Rate Limit), 503 (Service nicht verfügbar) und vorübergehenden Netzwerkfehlern.
Antworten cachen, um erneutes Crawlen zu vermeiden
In der Entwicklung führst du dein Skript oft mehrfach aus, während du die Parsing-Logik anpasst. Ohne Caching wird bei jedem Lauf HN erneut für dieselben Daten angefragt. Die Bibliothek requests-cache löst das in zwei Zeilen:
1import requests_cache
2requests_cache.install_cache("hn_cache", expire_after=3600) # 1 Stunde Cache
Nach diesen Zeilen am Anfang deines Skripts werden alle requests.get()-Aufrufe automatisch in einer lokalen SQLite-Datenbank gecacht. Wenn du dein Skript innerhalb einer Stunde zehnmal startest, trifft nur der erste Lauf tatsächlich das Netzwerk. Das ist ein Tool, das — und das aus gutem Grund.
Crawling und Parsing trennen
Ein Muster, auf das erfahrene Scraper schwören: zuerst die Rohdaten herunterladen, danach parsen. So kannst du, falls die Parsing-Logik einen Fehler hat, nur den Parser korrigieren und die Daten erneut verarbeiten, ohne alles neu abzurufen.
1import os, json
2def crawl_and_save(story_ids, output_dir="raw_data"):
3 """Story-Daten abrufen und als rohes JSON auf der Festplatte speichern."""
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 # Bereits abgerufene Items überspringen
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.
13Dieser Zweiphasen-Ansatz ist besonders wertvoll, wenn du Hunderte Items scrapen und die Verarbeitung schnell iterieren möchtest.
14### Deinen Scraper nach Zeitplan automatisieren
15Für einen täglichen HN-Digest soll dein Scraper automatisch laufen. Zwei gängige Optionen:
16**Option 1: cron (Linux/Mac)**
17```bash
18# Jeden Tag um 8:30 Uhr UTC ausführen
1930 8 * * * /usr/bin/python3 /home/user/scrape_hn.py >> /home/user/scrape.log 2>&1
Option 2: GitHub Actions (kostenlos, kein Server nötig)
1name: Scrape Hacker News
2on:
3 schedule:
4 - cron: '30 8 * * *' # Täglich um 8:30 Uhr UTC
5 workflow_dispatch: # Manueller Start-Button
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
Ein paar Stolpersteine bei GitHub-Actions-Schedules: Alle Cron-Zeiten sind in UTC, Verzögerungen von 15–60 Minuten sind normal (nutze also Zeiten wie :30 statt :00), und GitHub kann geplante Workflows in Repos ohne Aktivität für 60 Tage deaktivieren. Füge immer workflow_dispatch hinzu, damit du für Tests manuell starten kannst.
Für eine einfachere Lösung lässt sich mit Thunderbits Scheduled Scraper ein Zeitplan in normaler Sprache beschreiben — etwa "jeden Morgen um 8 Uhr scrapen" — ganz ohne Server oder Cron-Setup.
Wenn Python überdimensioniert ist: Der No-Code-Weg für Hacker News
Ich bin hier ehrlich, auch wenn ich Python mag und mein Team Entwickler-Tools baut. Wenn du nur die heutigen Top 100 HN-Storys einmalig und sofort in einer Tabelle brauchst, ist ein Python-Skript oft unnötiger Aufwand. Schon das Setup — virtuelle Umgebung, Pakete installieren, Selektoren herausfinden — dauert länger als das eigentliche Sammeln der Daten.
Hier kommt ins Spiel. So funktioniert der Ablauf:
- Öffne
news.ycombinator.comin Chrome - Klicke auf das Thunderbit-Icon und dann auf "AI Suggest Fields"
- Die KI liest die Seite und schlägt Spalten vor: Title, URL, Score, Author, Comment Count, Time Posted
- Passe die Felder bei Bedarf an (umbenennen, entfernen oder eigene hinzufügen — du kannst sogar einen KI-Prompt ergänzen wie "Als AI/DevTools/Web/Other kategorisieren")
- Klicke auf "Scrape" — die Daten erscheinen als strukturierte Tabelle
- Exportiere nach Excel, Google Sheets, Airtable oder Notion
Zwei Klicks bis zu strukturierten Daten. Keine Selektoren, kein Code, keine Wartung.
Ein echter Vorteil: Thunderbits KI passt sich automatisch an Layout-Änderungen an. Klassische Scraper mit CSS-Selektoren brechen, wenn sich das Markup einer Seite ändert — und obwohl HNs HTML recht stabil ist, hat es sich bereits geändert (class="athing submission" wurde angepasst, span.titleline ersetzte das ältere a.storylink). Ein KI-gestützter Scraper liest die Seite jedes Mal neu und ist daher unempfindlich gegenüber geänderten Klassennamen.

Thunderbit übernimmt außerdem Pagination (klickt den "More"-Button auf HN automatisch) und das Scrapen von Unterseiten (öffnet die Kommentarseite jeder Story, um Diskussionsdaten zu holen). Für den Anwendungsfall entspricht das dem rekursiven API-Code aus Methode 2 — nur eben ohne eine einzige Zeile zu schreiben.
Die Abwägung ist simpel: Python ist die richtige Wahl, wenn du eigene Logik, komplexe Transformationen, automatisierte Pipeline-Prozesse oder Lernziele hast. Thunderbit ist die richtige Wahl, wenn du schnell Daten brauchst, keinen Code warten willst oder kein Entwickler bist. Nimm das Werkzeug, das zu deiner Situation passt.
Python vs. API vs. No-Code: Welche Methode solltest du wählen?
Hier ist die komplette Entscheidungsübersicht:
| Kriterium | BeautifulSoup (HTML) | Firebase API | Algolia API | Thunderbit (No-Code) |
|---|---|---|---|---|
| Benötigtes technisches Wissen | Python auf mittlerem Niveau | Python für Anfänger | Python für Anfänger | Keines |
| Einrichtungszeit | 10–15 Min. | 5–10 Min. | 5–10 Min. | 2 Min. |
| Wartungsaufwand | Mittel (Selektoren können brechen) | Niedrig (stabiles JSON) | Niedrig (stabiles JSON) | Keiner |
| Datentiefe | Nur Startseite | Jedes Item, Nutzer | Suche + Historie | Startseite + Unterseiten |
| Kommentare | Schwer | Einfach (rekursiv) | Einfach (verschachtelter Baum) | Subpage-Scraping |
| Historische Daten | Nein | Nein | Ja (vollständiges Archiv) | Nein |
| Exportoptionen | Selbst programmieren | Selbst programmieren | Selbst programmieren | Integriert (Excel, Sheets usw.) |
| Scheduling | cron / GitHub Actions | cron / GitHub Actions | cron / GitHub Actions | Integrierter Scheduler |
| Am besten für | Scraping lernen | Zuverlässige Pipelines | Recherche & Analyse | Schnelle Datenzüge |
Wenn du Python lernst oder etwas Eigenes baust, nimm Methode 1 oder 2. Wenn du historische Analysen brauchst, ergänze die Algolia API. Wenn du einfach nur die Daten ohne Code willst, .
Fazit und wichtigste Erkenntnisse
Jetzt hast du in deinem Werkzeugkasten:
- Zwei vollständige Python-Methoden zum Scrapen von Hacker News — BeautifulSoup für HTML-Parsing und die Firebase API für saubere JSON-Daten
- Pagination-Techniken für mehr als Seite 1, inklusive der Algolia API für historische Daten bis zurück ins Jahr 2007
- Export-Code für CSV, Excel und Google Sheets — denn Daten im Terminal helfen sonst niemandem im Team
- Produktionsmuster — Retry-Logik, Caching, Trennung von Crawling und Parsing sowie geplante Automatisierung per cron oder GitHub Actions
- Eine No-Code-Alternative für den Fall, dass Python mehr Werkzeug ist, als du gerade brauchst
Meine Empfehlung: Starte für die meisten Fälle mit der Firebase API (Methode 2). Sie ist sauberer, zuverlässiger und bietet Kommentarzugriff, ohne dass du verschachteltes HTML mühsam parsen musst. Ergänze die Algolia API, wenn du historische Daten brauchst. Und behalte als Lesezeichen, wenn du nur schnell eine Tabelle brauchst und kein komplettes Python-Projekt aufsetzen willst.
Wenn du tiefer einsteigen willst, versuche HN-Kommentare für zu scrapen, baue mit GitHub Actions eine tägliche Digest-Pipeline oder nutze die Algolia API, um zu verfolgen, wie sich Technologietrends im letzten Jahrzehnt verändert haben.
FAQs
Ist es legal, Hacker News zu scrapen?
HN-Daten sind öffentlich zugänglich, und Y Combinator stellt sogar eine offizielle API für den programmgesteuerten Zugriff bereit. Die der Seite erlaubt das Scrapen von lesbaren Inhalten (Startseite, Item-Seiten, Benutzerseiten), verlangt aber ein Crawl-Delay von 30 Sekunden. Wenn du diese Pause respektierst und keine interaktiven Endpunkte (Voting, Login) abfragst, bist du auf der sicheren Seite. Mehr zu den rechtlichen Aspekten findest du in unserem Leitfaden zu den .
Hat Hacker News eine offizielle API?
Ja. Die unter hacker-news.firebaseio.com/v0/ ist kostenlos, erfordert keine Authentifizierung und bietet Zugriff auf Stories, Kommentare, Nutzerprofile und alle Feed-Typen (Top, New, Best, Ask, Show, Jobs). Sie liefert sauberes JSON und hat kein ausdrücklich genanntes Rate Limit, obwohl ein höflicher Umgang mit der Anfragedichte immer empfehlenswert ist.
Wie scrape ich Hacker-News-Kommentare mit Python?
Mit der Firebase API rufst du ein Story-Item ab und erhältst sein kids-Feld (ein Array der IDs der Top-Level-Kommentare). Jeder Kommentar ist wiederum ein Item mit eigenem kids-Feld für Antworten. Laufe den Baum rekursiv mit einer Funktion durch, die jeden Kommentar und seine Kinder abruft. Im Abschnitt "Kommentare scrapen (rekursiver Baumdurchlauf)" oben findest du den vollständigen Code. Alternativ liefert der den gesamten verschachtelten Kommentarbaum in einer einzigen Anfrage — deutlich schneller bei kommentarstarken Stories.
Kann ich Hacker News auch ohne Code scrapen?
Ja. funktioniert als Chrome-Erweiterung — öffne HN, klicke auf "AI Suggest Fields", und das Tool erkennt automatisch Spalten wie Titel, URL, Score und Autor. Klicke auf "Scrape" und exportiere direkt nach Excel, Google Sheets, Airtable oder Notion. Es unterstützt Pagination und kann sogar Unterseiten besuchen, um Kommentardaten zu holen. Kein Python, keine Selektoren, keine Wartung.
Wie bekomme ich historische Hacker-News-Daten?
Die ist dafür das beste Werkzeug. Verwende den Endpunkt search_by_date mit numericFilters=created_at_i>TIMESTAMP, um nach Zeitraum zu filtern. Du kannst nach Stichwort suchen, nach Story-Typ filtern und durch bis zu 500 Ergebnisseiten blättern. Für umfangreiche historische Analysen sind außerdem öffentliche Datensätze verfügbar auf (vollständiges Archiv), (28 Millionen Datensätze) und (4 Millionen Stories).
Mehr erfahren