För några månader sedan ville jag bygga ett dagligt nyhetsutskick med de bästa Hacker News-artiklarna för vårt team på Thunderbit. Min första tanke var helt enkelt att bokmärka sajten och bläddra igenom den varje morgon. Det höll i ungefär tre dagar innan jag insåg att jag lade 20 minuter om dagen på att läsa rubriker och kopiera in länkar i ett kalkylark.
Hacker News är en av de mest koncentrerade och värdefulla källorna till tech-intelligens på internet — ungefär , runt 1 300 nya inlägg varje dag och cirka 13 000 kommentarer per dag. Oavsett om du vill följa nya tekniktrender, bevaka ditt varumärke, bygga en rekryteringspipeline från trådar som "Who's Hiring", eller bara försöka hålla koll på vad utvecklarvärlden bryr sig om, är manuell uppföljning en kamp du inte vinner.
Det goda nyheterna: att skrapa Hacker News med Python är förvånansvärt enkelt. I den här guiden går jag igenom två kompletta metoder — HTML-skrapning med BeautifulSoup och den officiella HN Firebase API:n — samt paginering, export av data, produktionsklara mönster och ett no-code-alternativ för när Python känns som överkurs.
Varför skrapa Hacker News med Python?
Hacker News är inte bara ännu en länksamlar-sajt. Det är ett kuraterat flöde drivet av communityn där de mest intressanta tekniknyheterna lyfts fram genom uppröster och aktiv diskussion. Publiken lutar starkt åt teknikproffs (ungefär ), och sajtens 66 % direkta trafik visar att detta är en lojal, återkommande läsarskara — inte tillfälliga besökare.
Här är några vanliga anledningar till att folk skrapar HN-data:
| Användningsområde | Vad du får |
|---|---|
| Dagligt tech-digest | Toppartiklar, poäng och länkar skickade till din inkorg eller Slack |
| Bevakning av varumärke/konkurrenter | Aviseringar när ditt företag eller din produkt nämns |
| Trendanalys | Följ vilka tekniker, språk eller ämnen som får fäste över tid |
| Rekrytering | Plocka ut jobbannonser, tech stacks och löneindikatorer ur trådar med "Who's Hiring" |
| Innehållsresearch | Hitta ämnen som presterar bra att skriva om eller dela |
| Sentimentanalys | Bedöm communityns åsikt om produkter, lanseringar eller förändringar i branschen |
Bolag värda över 400 miljarder dollar tillsammans — Stripe, Dropbox och Airbnb — tillskriver Hacker News viktig tidig feedback och sina första användare därifrån. Drew Houston lade upp Dropbox-demo på HN i april 2007, den nådde förstaplatsen och betaväntelistan exploderade från 5 000 till 75 000 användare på en enda dag. HN-data är alltså inte bara intressant — den är kommersiellt värdefull.
Datan är offentligt tillgänglig, men sajtens struktur gör manuell insamling trög och tidskrävande. Automation med Python är den praktiska lösningen.
Två sätt att skrapa Hacker News med Python: översikt
Den här guiden täcker två kompletta, körbara arbetssätt:
- HTML-skrapning med
requests+ BeautifulSoup — hämta rå HTML från news.ycombinator.com och parsa den för att extrahera story-data. Perfekt för att lära sig grunderna i web scraping och för att få exakt det som visas på sidan. - Den officiella Hacker News Firebase API:n — anropa JSON-endpoints direkt, utan att behöva parsa HTML. Bättre för stabila datapipelines, åtkomst till kommentarer och historisk data.
Här är en jämförelse sida vid sida för att hjälpa dig välja rätt metod:
| Kriterium | HTML-skrapning (requests + BS4) | HN Firebase API | Thunderbit (No-code) |
|---|---|---|---|
| Komplexitet vid uppstart | Medel (parsa HTML-selectors) | Låg (JSON-endpoints) | Ingen (2-klicks Chrome-tillägg) |
| Datans färskhet | Realtime på förstasidan | Realtime (valfritt objekt via ID) | Realtime |
| Risk för rate limit | Medel (robots.txt anger 30 s crawl delay) | Låg (officiell, generös) | Hanteras av Thunderbit |
| Åtkomst till kommentarer | Svårt (nästlad HTML) | Enkelt (rekursiva item-ID:n) | Funktion för skrapning av undersidor |
| Historisk data | Begränsad | Via Algolia Search API | Ej tillämpligt |
| Bäst för | Lära sig grunderna i scraping | Pålitliga datapipelines | Icke-utvecklare, snabba exporter |
Båda metoderna innehåller komplett, körbar Python-kod. Och om du bara vill ha datan utan att skriva någon kod alls, tar jag upp det också.
Innan du börjar
- Svårighetsgrad: Nybörjare till medel
- Tidsåtgång: cirka 15–20 minuter per metod
- Det här behöver du:
- Python 3.11+ installerat
- En terminal eller kodredigerare
- Chrome-webbläsare (om du vill inspektera HN:s HTML eller testa no-code-alternativet)
- (valfritt, för no-code-metoden)

Så ställer du in din Python-miljö
Innan vi börjar ta i HN-datan, låt oss förbereda miljön. Jag rekommenderar att du skapar en virtuell miljö så att projektets beroenden hålls rena.
1# Skapa och aktivera en virtuell miljö
2python3 -m venv hn-scraper
3# macOS/Linux:
4source hn-scraper/bin/activate
5# Windows:
6hn-scraper\Scripts\activate
7# Installera paketen vi behöver för båda metoderna
8pip install requests==2.33.1 beautifulsoup4==4.14.3 pandas==3.0.2 openpyxl==3.1.5
För produktionsmönster längre fram (cache och retries) vill du även ha:
1pip install requests-cache==1.3.1 tenacity==9.1.4
Inga särskilda API-nycklar, inga autentiseringstokens. HN:s data är öppen.
Metod 1: Skrapa Hacker News med Python med BeautifulSoup
Det här är det klassiska sättet — hämta HTML, parsa den och plocka ut datan du vill ha. Det är så de flesta lär sig web scraping, och HN:s enkla tabellbaserade layout gör den till en bra övningsmiljö.
Steg 1: Hämta Hacker News-förstasidan
Öppna din editor och skapa en fil som heter scrape_hn_bs4.py. Här är startkoden:
1import requests
2from bs4 import BeautifulSoup
3> This paragraph contains content that cannot be parsed and has been skipped.
4print(f"Status: {response.status_code}, Page length: {len(response.text)} chars")
Kör den. Du bör se Status: 200 och en sidlängd på ungefär 40 000–50 000 tecken. Det är den råa HTML-koden från HN:s förstasida, laddad i minnet och redo att parsa.
Steg 2: Förstå HTML-strukturen
HN använder en tabellbaserad layout — ingen modern CSS grid eller flexbox. Varje story på sidan består av två viktiga <tr>-rader:
- Story-raden (
<tr class="athing submission">): innehåller placering, titel och länk - Metadata-raden (nästa
<tr>): innehåller poäng, författare, tid och antal kommentarer
De viktiga selectors är:
span.titleline > a— storyns titel och URLspan.score— röstpoängen (t.ex. "118 points")a.hnuser— författarens användarnamnspan.age— när inlägget publicerades- Den sista
<a>i.subtextmed ordet "comment" i texten — antal kommentarer
Om du högerklickar på en storytitel i Chrome och väljer "Inspect" ser du något i stil med detta:
1<span class="titleline">
2 <a href="https://darkbloom.dev">Darkbloom – Private inference on idle Macs</a>
3</span>
Och metadata-raden under den:
1<span class="score" id="score_47788542">118 points</span>
2by <a href="user?id=twapi" class="hnuser">twapi</a>
3<span class="age" title="2026-04-16T04:06:39 1776312399">
4 <a href="item?id=47788542">2 hours ago</a>
5</span>
6| <a href="item?id=47788542">65 comments</a>
Att förstå dessa selectors är avgörande — om HN någon gång ändrar sin markup måste du uppdatera dem. (Spoiler: API-metoden slipper det problemet helt.)
Steg 3: Extrahera titlar, länkar och poäng
Nu till själva jobbet. Vi loopar igenom varje story-rad, hämtar titel och länk från story-raden och sedan poängen från metadata-raden direkt under.
1import requests
2from bs4 import BeautifulSoup
3from pprint import pprint
4> This paragraph contains content that cannot be parsed and has been skipped.
5stories = []
6story_rows = soup.select("tr.athing")
7for row in story_rows:
8 # Titel och URL från story-raden
9 title_tag = row.select_one("span.titleline > a")
10 if not title_tag:
11 continue
12 title = title_tag.get_text()
13 link = title_tag.get("href", "")
14 # Metadata från nästa rad
15 meta_row = row.find_next_sibling("tr")
16 score = 0
17 author = ""
18 comments = 0
19> This paragraph contains content that cannot be parsed and has been skipped.
20> This paragraph contains content that cannot be parsed and has been skipped.
21# Filtrera fram stories med minst 50 poäng, sorterade efter score
22top_stories = sorted(
23 [s for s in stories if s["score"] >= 50],
24 key=lambda x: x["score"],
25 reverse=True,
26)
27pprint(top_stories[:10])
Några kommentarer till koden:
- Walrus-operatorn (
:=) fungerar i Python 3.8+. Den låter oss tilldela och kontrollera i samma rad — praktiskt för valfria element somspan.scoresom inte finns på alla rader (t.ex. jobbannonser saknar score). - HN använder
\xa0(icke-brytande mellanslag) mellan siffran och ordet "comments", så vi delar på det. - Stories som länkar till andra HN-sidor (t.ex. "Ask HN"-poster) har relativa URL:er som börjar med
item?id=. Du kan vilja lägga tillhttps://news.ycombinator.com/framför dem.
Steg 4: Kör och se resultat
Spara och kör:
1python scrape_hn_bs4.py
Du bör se ett resultat i stil med:
1[{'author': 'twapi',
2 'comments': 65,
3 'score': 118,
4 'title': 'Darkbloom – Private inference on idle Macs',
5 'url': 'https://darkbloom.dev'},
6 {'author': 'sebg',
7 'comments': 203,
8 'score': 247,
9 'title': 'Show HN: I built an open-source Perplexity alternative',
10 'url': 'https://github.com/...'},
11 ...]
Det där är 30 stories från sida 1. Men HN har hundratals aktiva stories vid varje given tidpunkt. Paginering tar vi upp i en senare del.
Metod 2: Skrapa Hacker News med Python med den officiella API:n
HN Firebase API är det officiellt sanktionerade sättet att komma åt Hacker News-data. Ingen autentisering, inga API-nycklar, ingen HTML-parsning. Du får rena JSON-svar. Jag använder den här metoden för allt som måste fungera stabilt i produktion.
Viktiga API-endpoints du behöver känna till
Bas-URL:en är https://hacker-news.firebaseio.com/v0/. Här är de endpoints som spelar roll:
This paragraph contains content that cannot be parsed and has been skipped.
Ett story-objekt ser ut så här:
1{
2 "by": "twapi",
3 "descendants": 65,
4 "id": 47788542,
5 "kids": [47789171, 47788769, 47788762],
6 "score": 118,
7 "time": 1776312399,
8 "title": "Darkbloom – Private inference on idle Macs",
9 "type": "story",
10 "url": "https://darkbloom.dev"
11}
Fältet kids innehåller ID:n för direkt underliggande kommentarer. Varje kommentar är i sig ett item som kan ha egna kids — det är så kommentarsträdet är uppbyggt.
Steg 1: Hämta ID:n för toppstories
Skapa en fil som heter scrape_hn_api.py:
1import requests
2import time
3from pprint import pprint
4API_BASE = "https://hacker-news.firebaseio.com/v0"
5# Hämta ID:n för toppstories
6response = requests.get(f"{API_BASE}/topstories.json")
7story_ids = response.json()
8print(f"Fick {len(story_ids)} ID:n för toppstories")
9# Output: Fick 500 ID:n för toppstories
500 story-ID:n i en enda request — ingen parsning, inga selectors, bara en JSON-array.
Steg 2: Hämta story-detaljer via ID
Nu behöver vi själva storydatan. Här visar sig fan-out-problemet: 500 stories innebär 500 enskilda API-anrop. I mina tester tog varje item-request ungefär 1,2 sekunder sekventiellt. För 500 stories blir det ungefär 10 minuter.
För de flesta användningsfall behöver du inte alla 500. Här är kod för att hämta de 30 översta:
1def fetch_story(story_id):
2 """Hämta detaljer för en enskild story från HN API."""
3 resp = requests.get(f"{API_BASE}/item/{story_id}.json")
4 return resp.json()
5> This paragraph contains content that cannot be parsed and has been skipped.
6# Sortera efter score, visa topp 10
7top = sorted(stories, key=lambda x: x["score"], reverse=True)[:10]
8pprint(top)
time.sleep(0.1) lägger in en liten hövlig paus. Firebase API:t har ingen uttalad rate limit, men att bombardera vilket API som helst utan pauser är dålig stil.
Steg 3: Skrapa kommentarer (rekursiv trädvandring)
Här blir API:t verkligen bättre än HTML-skrapning. Kommentarer på HN är djupt nästlade — svar på svar på svar. I HTML innebär det att man måste parsa komplexa nästlade tabellstrukturer. Med API:t ger varje kommentars kids-fält ID:n för dess barn, och du kan bara vandra trädet rekursivt.
1def fetch_comments(item_id, depth=0, max_depth=3):
2 """Hämta kommentarer rekursivt upp till max_depth."""
3 item = requests.get(f"{API_BASE}/item/{item_id}.json").json()
4 if not item or item.get("type") != "comment":
5 return []
6> This paragraph contains content that cannot be parsed and has been skipped.
7 if depth < max_depth and item.get("kids"):
8 for kid_id in item["kids"]:
9 comments.extend(fetch_comments(kid_id, depth + 1, max_depth))
10 time.sleep(0.05)
11 return comments
12# Exempel: hämta kommentarer för top-storyn
13if stories:
14 top_story = stories[0]
15 top_story_full = requests.get(f"{API_BASE}/item/{top_story['id']}.json").json()
16 if top_story_full.get("kids"):
17 print(f"\nKommentarer för: {top_story['title']}")
18 all_comments = []
19 for kid_id in top_story_full["kids"][:5]: # Första 5 kommentarerna på toppnivå
20 all_comments.extend(fetch_comments(kid_id, depth=0, max_depth=2))
21 time.sleep(0.1)
22 for c in all_comments[:15]:
23 indent = " " * c["depth"]
24 preview = c["text"][:80].replace("\n", " ") if c["text"] else "[no text]"
25 print(f"{indent}[{c['author']}] {preview}...")
Det här rekursiva arbetssättet är betydligt enklare än att försöka parsa nästlade kommentarstrådar i HTML. Om du behöver hela kommentarsträd är API:t rätt väg.
Steg 4: Kör och se resultat
1python scrape_hn_api.py
Du kommer att se strukturerad story-data följt av en nästlad kommentarförhandsvisning. Datan är renare, åtkomsten till kommentarer är trivial och det finns ingen risk att din scraper går sönder bara för att HN bytt namnet på en CSS-klass.
Bortom sida 1: paginering och historisk data
De flesta guider för HN-skrapning stannar vid sida 1 — 30 stories. Det duger för en snabb demo, men verkliga användningsfall behöver ofta mer djup.
Skrapa flera sidor med BeautifulSoup
HN:s paginering använder ett enkelt URL-mönster: ?p=2, ?p=3 osv. Varje sida returnerar 30 stories, och sajten serverar upp till ungefär sida 20 (sammanlagt runt 600 stories). Efter det får du tomma sidor.
1import time
2def scrape_hn_pages(num_pages=5):
3 """Skrapa flera sidor från HN:s förstasida."""
4 all_stories = []
5 for page in range(1, num_pages + 1):
6 url = f"https://news.ycombinator.com/news?p={page}"
7 response = requests.get(url, headers=headers)
8 soup = BeautifulSoup(response.text, "html.parser")
9 story_rows = soup.select("tr.athing")
10 if not story_rows:
11 print(f"Sida {page}: inga stories hittades, stoppar.")
12 break
13 for row in story_rows:
14 title_tag = row.select_one("span.titleline > a")
15 if not title_tag:
16 continue
17 meta_row = row.find_next_sibling("tr")
18 score = 0
19 if meta_row and (score_tag := meta_row.select_one("span.score")):
20 score = int(score_tag.get_text().replace(" points", ""))
21> This paragraph contains content that cannot be parsed and has been skipped.
22 print(f"Sida {page}: skrapade {len(story_rows)} stories")
23 # Respektera robots.txt:s crawl-delay på 30 sekunder
24 if page < num_pages:
25 time.sleep(30)
26 return all_stories
27stories = scrape_hn_pages(5)
28print(f"\nTotalt antal skrapade stories: {len(stories)}")
time.sleep(30) är viktigt. HN:s begär uttryckligen 30 sekunders crawl delay. Ignorerar du det riskerar du rate limiting (HTTP 429) eller tillfälligt blockering. Fem sidor med 30 sekunders mellanrum tar ungefär 2,5 minuter — inte direkt, men respektfullt.
För dig som inte vill hantera pagineringskod själv hanterar klickbaserad och oändlig scroll-paginering automatiskt. Den klickar på "More"-knappen längst ner på HN-sidorna utan någon konfiguration.
Åtkomst till historisk Hacker News-data med Algolia API
Firebase API:t ger dig aktuell data. För historisk analys — "Vilka var de bästa Python-artiklarna 2023?" eller "Hur har AI-bevakningen förändrats de senaste 5 åren?" — behöver du .
1import requests
2ALGOLIA_BASE = "https://hn.algolia.com/api/v1"
3> This paragraph contains content that cannot be parsed and has been skipped.
4# Exempel: hitta Python-skrapningsstories med 10+ poäng sedan jan 2024
5results = search_hn(
6 query="python scraping",
7 tags="story",
8)
9print(f"Hittade {results['nbHits']} resultat totalt")
10for hit in results["hits"][:5]:
11 print(f" [{hit.get('points', 0)} poäng] {hit['title']}")
För datumfiltrerade sökningar använder du numericFilters:
1import calendar, datetime
2# Stories sedan 1 januari 2024
3start_date = datetime.datetime(2024, 1, 1)
4start_ts = int(calendar.timegm(start_date.timetuple()))
5> This paragraph contains content that cannot be parsed and has been skipped.
6Algolia API:t är snabbt (5–9 ms serverbearbetningstid), kräver ingen API-nyckel och stödjer paginering upp till 500 sidor. För historisk bulk-analys är det bästa alternativet.
7## Exportera skrapad Hacker News-data till CSV, Excel och Google Sheets
8Varje HN-guidning jag sett slutar med `pprint()`-utskrift i terminalen. Det är bra för felsökning, men om du bygger ett dagligt digest eller gör trendanalys behöver du datan i en fil. Så här gör du det.
9### Exportera till CSV med Python
10```python
11import csv
12def export_to_csv(stories, filename="hn_stories.csv"):
13 """Spara skrapade stories till en CSV-fil."""
14 fieldnames = ["title", "url", "score", "author", "comments"]
15 with open(filename, "w", newline="", encoding="utf-8") as f:
16 writer = csv.DictWriter(f, fieldnames=fieldnames)
17 writer.writeheader()
18 writer.writerows(stories)
19 print(f"Sparade {len(stories)} stories till {filename}")
20export_to_csv(stories)
Exportera till Excel med Python
1import pandas as pd
2def export_to_excel(stories, filename="hn_stories.xlsx"):
3 """Spara skrapade stories till en Excel-fil."""
4 df = pd.DataFrame(stories)
5 df.to_excel(filename, index=False, engine="openpyxl")
6 print(f"Sparade {len(stories)} stories till {filename}")
7export_to_excel(stories)
Se till att openpyxl är installerat — pandas använder det som Excel-motor. Om det saknas får du ett ImportError.
Skicka till Google Sheets (valfritt)
För automatiserade arbetsflöden kanske du vill skicka datan direkt till Google Sheets med biblioteket gspread. Då behöver du sätta upp ett Google Cloud service account (en engångsprocess):
1import gspread
2gc = gspread.service_account(filename="service_account.json")
3sh = gc.open("HN Daily Digest")
4worksheet = sh.sheet1
5# Konvertera stories till rader
6header = list(stories[0].keys())
7rows = [list(s.values()) for s in stories]
8worksheet.clear()
9worksheet.update([header] + rows)
10print("Skickade till Google Sheets")
No-code-alternativet för export
Om det låter som mer jobb att sätta upp service accounts och skriva exportkod än själva skrapningen, så förstår jag det. På Thunderbit har vi byggt gratis dataexport som låter dig skicka skrapad data direkt till Excel, Google Sheets, Airtable eller Notion — ingen kod, inga credentials, ingen pipeline att underhålla. För en engångshämtning är det faktiskt snabbare. Mer om det längre ner.
Gör din scraper produktionsklar: felhantering, cache och schemaläggning
Om du kör en scraper en gång för skojs skull duger koden ovan. Om du kör den dagligen som del av ett arbetsflöde behöver du några saker till.
Felhantering och retry-logik
Nätverk går ner. Servrar stryper trafik. Ett enda misslyckat anrop ska inte krascha hela din scraping. Här är en retry-funktion med exponentiell backoff:
1from tenacity import retry, stop_after_attempt, wait_exponential_jitter
2import requests
3@retry(stop=stop_after_attempt(5), wait=wait_exponential_jitter(initial=1, max=60))
4def fetch_with_retry(url):
5 """Hämta en URL med automatiska retries och exponentiell backoff."""
6 response = requests.get(url, timeout=10)
7 response.raise_for_status()
8 return response
9# Användning:
10try:
11 resp = fetch_with_retry("https://hacker-news.firebaseio.com/v0/topstories.json")
12 story_ids = resp.json()
13except Exception as e:
14 print(f"Misslyckades efter retries: {e}")
Biblioteket tenacity hanterar retry-logiken snyggt. Det försöker upp till 5 gånger med jitterad exponentiell backoff — från 1 sekund och upp till 60 sekunder. Det hanterar HTTP 429 (rate limited), 503 (service unavailable) och tillfälliga nätverksfel på ett bra sätt.
Cacha svar för att slippa skrapa om och om igen
Under utveckling kör du ofta scrapern många gånger medan du justerar parsningen. Utan cache träffar varje körning HN:s servrar igen för samma data. Biblioteket requests-cache löser det på två rader:
1import requests_cache
2requests_cache.install_cache("hn_cache", expire_after=3600) # Cacha i 1 timme
Efter att du lagt till de här raderna högst upp i skriptet cachas alla requests.get()-anrop automatiskt i en lokal SQLite-databas. Kör du skriptet 10 gånger på en timme är det bara första körningen som faktiskt går ut på nätet. Det här är ett verktyg , och med god anledning.
Separera insamling från parsning
Ett mönster erfarna scraper-utvecklare svär vid: hämta rådata först, parsa sedan. Då kan du, om parsningen har en bugg, fixa den och köra om utan att hämta om datan.
1import os, json
2def crawl_and_save(story_ids, output_dir="raw_data"):
3 """Hämta story-data och spara rå JSON på disk."""
4 os.makedirs(output_dir, exist_ok=True)
5 for sid in story_ids:
6 filepath = os.path.join(output_dir, f"{sid}.json")
7 if os.path.exists(filepath):
8 continue # Hoppa över objekt som redan hämtats
9 resp = fetch_with_retry(f"{API_BASE}/item/{sid}.json")
10 with open(filepath, "w") as f:
11 json.dump(resp.json(), f)
12> This paragraph contains content that cannot be parsed and has been skipped.
13Det här tvåstegsupplägget är särskilt värdefullt när du skrapar hundratals objekt och vill iterera snabbt på hur datan bearbetas.
14### Automatisera din scraper på schema
15För ett dagligt HN-digest behöver scrapern köras automatiskt. Två vanliga alternativ:
16**Alternativ 1: cron (Linux/Mac)**
17```bash
18# Kör varje dag kl. 08:30 UTC
1930 8 * * * /usr/bin/python3 /home/user/scrape_hn.py >> /home/user/scrape.log 2>&1
Alternativ 2: GitHub Actions (gratis, ingen server behövs)
1name: Scrape Hacker News
2on:
3 schedule:
4 - cron: '30 8 * * *' # Dagligen kl. 08:30 UTC
5 workflow_dispatch: # Manuell trigger-knapp
6jobs:
7 scrape:
8 runs-on: ubuntu-latest
9 steps:
10 - uses: actions/checkout@v4
11 - uses: actions/setup-python@v6
12 with:
13 python-version: '3.12'
14 - run: pip install requests beautifulsoup4 pandas openpyxl
15 - run: python scrape_hn.py
16 - run: |
17 git config user.name "GitHub Actions Bot"
18 git config user.email "actions@github.com"
19 git add -A
20 git diff --staged --quiet || git commit -m "Uppdatera HN-data $(date -u +%Y-%m-%dT%H:%M:%SZ)"
21 git push
Några fallgropar med schemaläggning i GitHub Actions: alla cron-tider är i UTC, förseningar på 15–60 minuter är vanliga (använd tider som :30 i stället för :00), och GitHub kan inaktivera schemalagda workflows för repos utan aktivitet i 60 dagar. Inkludera alltid workflow_dispatch så att du kan köra manuellt vid test.
För ett enklare alternativ låter Thunderbit’s Scheduled Scraper-funktion dig beskriva schemat i vanlig text — något i stil med "skrapa varje morgon kl. 8" — utan server eller cron-konfiguration.
När Python är överkurs: no-code-sättet att skrapa Hacker News
Jag ska vara ärlig här, även om jag älskar Python och mitt team bygger utvecklarverktyg. Om du bara behöver dagens 100 bästa HN-stories i ett kalkylark — direkt, en gång — är det onödigt mycket arbete att skriva, felsöka och köra ett Python-skript. Bara uppsättningen (virtuell miljö, installera paket, lista ut selectors) tar längre tid än själva datainsamlingen.
Det är här passar in. Så här fungerar det:
- Öppna
news.ycombinator.comi Chrome - Klicka på Thunderbit-ikonen och sedan "AI Suggest Fields"
- AI:n läser sidan och föreslår kolumner: Title, URL, Score, Author, Comment Count, Time Posted
- Justera fälten om du vill (byt namn, ta bort eller lägg till egna — du kan till och med lägga till en AI-prompt som "Klassificera som AI/DevTools/Web/Other")
- Klicka på "Scrape" — datan visas i en strukturerad tabell
- Exportera till Excel, Google Sheets, Airtable eller Notion
Två klick till strukturerad data. Inga selectors, ingen kod, inget underhåll.
En verklig fördel här: Thunderbits AI anpassar sig automatiskt när layouten ändras. Traditionella scrapers med CSS-selectors går sönder när en sajt ändrar markup — och även om HN:s HTML är ganska stabil har den ändrats (klassen class="athing submission" uppdaterades, span.titleline ersatte den äldre a.storylink). En AI-driven scraper läser sidan på nytt varje gång, så den bryr sig inte om ändringar i klassnamn.

Thunderbit hanterar också paginering (den klickar automatiskt på HN:s "More"-knapp) och skrapning av undersidor (den besöker varje stories kommentarsida för att hämta diskussionsdata). För use case med är det motsvarigheten till den rekursiva API-koden i metod 2 — men utan att du skriver en enda rad.
Avvägningen är enkel: Python är rätt val när du behöver egen logik, komplex datatransformering, schemalagda automatiserade pipelines eller om du lär dig koda. Thunderbit är rätt val när du vill ha data snabbt, inte vill underhålla kod eller inte är utvecklare. Välj det verktyg som passar situationen.
Python vs. API vs. no-code: vilken metod ska du välja?
Här är hela beslutsramverket:
| Kriterium | BeautifulSoup (HTML) | Firebase API | Algolia API | Thunderbit (No-code) |
|---|---|---|---|---|
| Teknisk nivå som krävs | Medelgod Python | Nybörjar-Python | Nybörjar-Python | Ingen |
| Tid för uppsättning | 10–15 min | 5–10 min | 5–10 min | 2 min |
| Underhållsbehov | Medel (selectors kan gå sönder) | Låg (stabil JSON) | Låg (stabil JSON) | Inget |
| Datadjup | Endast förstasidan | Valfritt item, användare | Sök + historik | Förstasida + undersidor |
| Kommentarer | Svårt | Enkelt (rekursivt) | Enkelt (nästlat träd) | Skrapning av undersidor |
| Historisk data | Nej | Nej | Ja (fullt arkiv) | Nej |
| Exportalternativ | Bygg själv i kod | Bygg själv i kod | Bygg själv i kod | Inbyggt (Excel, Sheets, etc.) |
| Schemaläggning | cron / GitHub Actions | cron / GitHub Actions | cron / GitHub Actions | Inbyggd schemaläggare |
| Bäst för | Lära sig scraping | Pålitliga pipelines | Research och analys | Snabba datauttag |
Om du lär dig Python eller bygger något skräddarsytt, välj metod 1 eller 2. Om du behöver historisk analys, lägg till Algolia API. Om du bara vill ha datan utan kod, .
Slutsats och viktigaste lärdomar
Nu har du följande i verktygslådan:
- Två kompletta Python-metoder för att skrapa Hacker News — BeautifulSoup för HTML-parsning och Firebase API för rena JSON-data
- Pagineringstekniker för att skrapa bortom sida 1, inklusive Algolia API för historisk data tillbaka till 2007
- Exportkod för CSV, Excel och Google Sheets — eftersom data i terminalen inte hjälper någon annan i teamet
- Produktionsmönster — retry-logik, cache, separation mellan crawl och parsing, samt schemalagd automation via cron eller GitHub Actions
- Ett no-code-alternativ för när Python är mer verktyg än du behöver
Min rekommendation: börja med Firebase API (metod 2) för de flesta användningsfall. Det är renare, mer pålitligt och ger dig tillgång till kommentarer utan huvudvärken med att parsa nästlad HTML. Lägg till Algolia API när du behöver historisk data. Och spara i bokmärkena för de tillfällen då du bara behöver ett snabbt kalkylark och inte vill starta ett helt Python-projekt.
Om du vill gå djupare kan du testa att skrapa HN-kommentarer för , bygga en daglig digest-pipeline med GitHub Actions eller utforska Algolia API för att följa hur tekniktrender har förändrats under det senaste decenniet.
Vanliga frågor
Är det lagligt att skrapa Hacker News?
HN:s data är offentligt tillgänglig, och Y Combinator tillhandahåller ett officiellt API just för programmatisk åtkomst. Sajtens tillåter skrapning av innehåll som bara kan läsas (förstasida, item-sidor, användarsidor) men begär 30 sekunders crawl delay. Respektera fördröjningen, skrapa inte interaktiva endpoints (röstning, inloggning), så är du på säker mark. För mer om etik kring scraping, se vår guide om .
Finns det ett officiellt API för Hacker News?
Ja. på hacker-news.firebaseio.com/v0/ är gratis, kräver ingen autentisering och ger åtkomst till stories, kommentarer, användarprofiler och alla feed-typer (top, new, best, ask, show, jobs). Det returnerar ren JSON och har ingen uttalad rate limit, även om det alltid är klokt att vara försiktig med hur ofta du skickar anrop.
Hur skrapar jag Hacker News-kommentarer med Python?
Med Firebase API hämtar du ett story-objekt för att få dess kids-fält (en array med ID:n för kommentarer på toppnivå). Varje kommentar är i sin tur ett item med eget kids-fält för svar. Gå igenom trädet rekursivt med en funktion som hämtar varje kommentar och dess barn. Se avsnittet "Skrapa kommentarer (rekursiv trädvandring)" ovan för komplett kod. Alternativt returnerar hela nästlade kommentarsträdet i ett enda anrop — mycket snabbare för stories med många kommentarer.
Kan jag skrapa Hacker News utan att skriva kod?
Ja. fungerar som ett Chrome-tillägg — öppna HN, klicka på "AI Suggest Fields", så identifierar det automatiskt kolumner som titel, URL, score och author. Klicka på "Scrape" och exportera direkt till Excel, Google Sheets, Airtable eller Notion. Det hanterar paginering och kan till och med besöka undersidor för att hämta kommentardata. Ingen Python, inga selectors, inget underhåll.
Hur får jag historisk Hacker News-data?
är bästa verktyget för detta. Använd search_by_date-endpointen med numericFilters=created_at_i>TIMESTAMP för att filtrera på datumintervall. Du kan söka på nyckelord, filtrera på story-typ och bläddra igenom upp till 500 sidor med resultat. För större historiska analyser finns också publika dataset på (fullt arkiv), (28 miljoner poster) och (4 miljoner stories).
Läs mer