Comment je scrape Hacker News avec Python (2 méthodes, code complet)

Dernière mise à jour le April 16, 2026

Il y a quelques mois, je voulais monter un récap quotidien des meilleures actualités Hacker News pour l’équipe Thunderbit. Mon premier réflexe, c’était juste de mettre le site en favori et d’aller le parcourir chaque matin. Au bout de trois jours, j’ai compris que je passais déjà 20 minutes par jour à lire des titres et à faire des copier-coller de liens dans un tableur.

Hacker News est l’une des sources les plus riches et les plus denses d’infos tech sur internet — environ , près de 1 300 nouveaux sujets publiés chaque jour et autour de 13 000 commentaires générés quotidiennement. Que tu suives les dernières tendances tech, que tu surveilles ta marque, que tu construises un vivier de recrutement à partir des fils « Who’s Hiring », ou que tu veuilles simplement rester à jour sur ce qui compte pour les développeurs, tout faire à la main, c’est perdu d’avance.

La bonne nouvelle : extraire Hacker News avec Python est étonnamment simple. Dans ce guide, je te montre deux méthodes complètes — le scraping HTML avec BeautifulSoup et l’API officielle HN Firebase — avec pagination, export des données, bonnes pratiques prêtes pour la prod, et une alternative sans code quand Python te paraît trop lourd.

Pourquoi scraper Hacker News avec Python ?

Hacker News, ce n’est pas juste un agrégateur de liens. C’est un flux éditorialisé, porté par la communauté, où les sujets tech les plus intéressants remontent grâce aux votes et aux discussions actives. Son audience est très orientée vers les profils tech (environ ), et son taux de trafic direct de 66 % montre qu’il s’agit d’une audience fidèle et régulière — pas de simples visiteurs de passage.

Voici pourquoi on extrait les données de HN :

Cas d’usageCe que vous obtenez
Récap tech quotidienLes meilleurs sujets, scores et liens envoyés dans votre boîte mail ou Slack
Veille marque / concurrentsDes alertes quand votre entreprise ou votre produit est mentionné
Analyse des tendancesSuivre les technologies, langages ou sujets qui gagnent en popularité au fil du temps
RecrutementExploiter les fils "Who’s Hiring" pour identifier des offres, des stacks techniques et des signaux salariaux
Recherche éditorialeTrouver des sujets performants à traiter ou à partager
Analyse de sentimentMesurer l’opinion de la communauté sur des produits, des lancements ou des évolutions du secteur

Des boîtes valorisées à plus de 400 milliards de dollars au total — Stripe, Dropbox, Airbnb — attribuent à Hacker News une partie de leurs premiers retours et de leurs premiers utilisateurs. En avril 2007, Drew Houston a posté la démo de Dropbox sur HN, le sujet est monté numéro 1, et la liste d’attente de la bêta est passée de 5 000 à 75 000 utilisateurs en une seule journée. Les données de HN ne sont pas seulement intéressantes : elles ont une vraie valeur business.

Les données sont publiques, mais la structure du site rend la collecte manuelle fastidieuse. L’automatisation avec Python est la solution la plus pratique.

Deux façons de scraper Hacker News avec Python : vue d’ensemble

Ce guide couvre deux approches complètes et exécutable :

  1. Scraping HTML avec requests + BeautifulSoup — récupérer le HTML brut de news.ycombinator.com et l’analyser pour extraire les données des sujets. Idéal pour apprendre les bases du scraping et récupérer exactement ce qui s’affiche sur la page.
  2. L’API officielle Hacker News Firebase — interroger directement des endpoints JSON, sans parsing HTML. Plus adaptée aux pipelines de données fiables, à l’accès aux commentaires et aux données historiques.

Voici une comparaison côte à côte pour t’aider à choisir la bonne solution :

CritèreScraping HTML (requests + BS4)API HN FirebaseThunderbit (sans code)
Complexité de mise en placeMoyenne (sélecteurs HTML à analyser)Faible (endpoints JSON)Aucune (extension Chrome en 2 clics)
Fraîcheur des donnéesPage d’accueil en temps réelTemps réel (n’importe quel item par ID)Temps réel
Risque de limite de requêtesMoyen (robots.txt impose 30 s de délai)Faible (API officielle, généreuse)Géré par Thunderbit
Accès aux commentairesDifficile (HTML imbriqué)Facile (IDs d’items récursifs)Fonction de scraping des sous-pages
Données historiquesLimitéesVia l’API de recherche AlgoliaN/A
Idéal pourApprendre les bases du scrapingPipelines de données fiablesNon-développeurs, exports rapides

Les deux méthodes incluent du code Python complet et exécutable. Et si tu veux juste les données sans écrire une seule ligne de code, je vais aussi te montrer comment faire.

Avant de commencer

  • Niveau : Débutant à intermédiaire
  • Temps nécessaire : environ 15–20 minutes par méthode
  • Ce dont tu as besoin :
    • Python 3.11+ installé
    • Un terminal ou un éditeur de code
    • Le navigateur Chrome (si tu veux inspecter le HTML de HN ou tester l’option sans code)
    • (optionnel, pour la méthode sans code)

scrape-hacker-news-methods.webp

Configuration de l’environnement Python

Avant de manipuler les données HN, préparons l’environnement. Je te conseille de créer un environnement virtuel pour garder des dépendances propres.

1# Créer et activer un environnement virtuel
2python3 -m venv hn-scraper
3# macOS/Linux:
4source hn-scraper/bin/activate
5# Windows:
6hn-scraper\Scripts\activate
7# Installer les packages nécessaires pour les deux méthodes
8pip install requests==2.33.1 beautifulsoup4==4.14.3 pandas==3.0.2 openpyxl==3.1.5

Pour les bonnes pratiques de production plus loin (cache, retries), tu auras aussi besoin de :

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

Pas de clé API, pas de jeton d’authentification. Les données de HN sont ouvertes.

Méthode 1 : scraper Hacker News avec Python et BeautifulSoup

C’est l’approche classique : récupérer le HTML, l’analyser et en extraire les données souhaitées. C’est comme ça que la plupart des gens apprennent le web scraping, et la structure simple de HN en fait un très bon terrain d’entraînement.

Étape 1 : récupérer la page d’accueil de Hacker News

Ouvre ton éditeur et crée un fichier nommé scrape_hn_bs4.py. Voici le code de départ :

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

Lance-le. Tu devrais voir Status: 200 et une longueur de page d’environ 40 000 à 50 000 caractères. C’est le HTML brut de la page d’accueil de HN, chargé en mémoire et prêt à être analysé.

Étape 2 : comprendre la structure HTML

HN utilise une mise en page basée sur des tableaux — pas de grille CSS moderne ni de flexbox. Chaque sujet sur la page se compose de deux lignes <tr> clés :

  • La ligne du sujet (<tr class="athing submission">) : contient le rang, le titre et le lien
  • La ligne des métadonnées (le <tr> suivant) : contient les points, l’auteur, l’heure et le nombre de commentaires

Les sélecteurs importants :

  • span.titleline > a — le titre et l’URL du sujet
  • span.score — le nombre de votes (par exemple « 118 points »)
  • a.hnuser — le nom d’utilisateur de l’auteur
  • span.age — l’heure de publication
  • Le dernier <a> dans .subtext contenant le mot « comment » — le nombre de commentaires

Si tu fais un clic droit sur un titre dans Chrome puis « Inspecter », tu verras quelque chose comme :

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

Puis la ligne de métadonnées juste en dessous :

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>

Comprendre ces sélecteurs est essentiel : si HN change un jour son balisage, tu devras les mettre à jour. (Petit spoiler : la méthode API évite complètement ce problème.)

Étape 3 : extraire les titres, liens et scores

Passons au concret. Nous allons parcourir chaque ligne de sujet, récupérer le titre et le lien depuis la ligne du sujet, puis récupérer le score depuis la ligne de métadonnées juste en dessous.

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    # Titre et URL depuis la ligne du sujet
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    # Métadonnées depuis la ligne suivante
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 les sujets avec 50+ points, triés par 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])

Quelques remarques sur ce code :

  • L’opérateur walrus (:=) fonctionne à partir de Python 3.8. Il permet d’assigner et de tester en une seule ligne — pratique pour les éléments optionnels comme span.score, qui n’existe pas sur toutes les lignes (par exemple les offres d’emploi n’ont pas de score).
  • HN utilise \xa0 (espace insécable) entre le nombre et « comments », donc on découpe sur ce caractère.
  • Les sujets qui renvoient vers d’autres pages HN (comme les posts « Ask HN ») auront des URL relatives commençant par item?id=. Tu peux vouloir leur ajouter https://news.ycombinator.com/.

Étape 4 : exécuter et voir le résultat

Enregistre puis lance :

1python scrape_hn_bs4.py

Tu devrais obtenir un résultat comme :

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

Cela correspond aux 30 sujets de la page 1. Mais Hacker News compte à tout moment des centaines de sujets actifs. On verra la pagination plus loin.

Méthode 2 : scraper Hacker News avec Python grâce à l’API officielle

L’API HN Firebase est la méthode officiellement recommandée pour accéder aux données Hacker News. Pas d’authentification, pas de clé API, pas de parsing HTML. Tu reçois des réponses JSON propres. Je privilégie cette méthode pour tout ce qui doit marcher de manière fiable en production.

Endpoints API essentiels à connaître

L’URL de base est https://hacker-news.firebaseio.com/v0/. Voici les endpoints utiles :

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

Un sujet ressemble à ceci :

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}

Le champ kids contient les IDs des commentaires enfants directs. Chaque commentaire est lui aussi un item qui peut avoir ses propres kids — c’est comme ça que l’arbre des commentaires est structuré.

Étape 1 : récupérer les IDs des meilleurs sujets

Crée un fichier appelé scrape_hn_api.py :

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

500 IDs de sujets en une seule requête — aucun parsing, aucun sélecteur, juste un tableau JSON.

Étape 2 : récupérer le détail d’un sujet par ID

On a maintenant besoin des vraies données. C’est ici que le problème de fan-out apparaît : 500 sujets = 500 appels API individuels. Dans mes tests, chaque requête d’item prend environ 1,2 seconde en séquentiel. Pour 500 sujets, ça représente environ 10 minutes.

Pour la plupart des cas d’usage, tu n’as pas besoin des 500. Voici le code pour récupérer les 30 premiers :

1def fetch_story(story_id):
2    """Récupère les détails d’un sujet via l’API HN."""
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# Trier par score et afficher les 10 premiers
7top = sorted(stories, key=lambda x: x["score"], reverse=True)[:10]
8pprint(top)

Le time.sleep(0.1) ajoute une petite pause de courtoisie. L’API Firebase n’annonce pas de limite de requêtes précise, mais marteler n’importe quelle API sans pause n’est pas une bonne pratique.

Étape 3 : scraper les commentaires (parcours récursif de l’arbre)

C’est là que l’API prend vraiment l’avantage sur le scraping HTML. Les commentaires sur HN sont profondément imbriqués — réponses à des réponses à des réponses. En HTML, ça veut dire analyser des structures de tableaux complexes et imbriquées. Avec l’API, chaque commentaire fournit dans kids les IDs de ses enfants, et il suffit de parcourir l’arbre récursivement.

1def fetch_comments(item_id, depth=0, max_depth=3):
2    """Récupère récursivement les commentaires jusqu’à 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# Exemple : récupérer les commentaires du premier sujet
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"\nComments for: {top_story['title']}")
18        all_comments = []
19        for kid_id in top_story_full["kids"][:5]:  # 5 premiers commentaires de niveau 1
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}...")

Cette approche récursive est bien plus simple que d’essayer d’analyser des fils de commentaires HTML imbriqués. Si tu as besoin d’arbres de commentaires complets, l’API est la bonne solution.

Étape 4 : exécuter et voir le résultat

1python scrape_hn_api.py

Tu verras des données de sujet structurées, suivies d’un aperçu des commentaires imbriqués. Les données sont plus propres, l’accès aux commentaires est trivial, et tu n’as aucun risque de casser ton scraper parce que HN a changé un nom de classe CSS.

Aller au-delà de la page 1 : pagination et données historiques

La plupart des tutos HN s’arrêtent à la page 1 — 30 sujets. C’est suffisant pour une démo rapide, mais les vrais cas d’usage demandent souvent plus de profondeur.

Scraper plusieurs pages avec BeautifulSoup

La pagination de HN utilise une simple convention d’URL : ?p=2, ?p=3, etc. Chaque page renvoie 30 sujets, et le site sert jusqu’à environ la page 20 (soit environ 600 sujets au total). Au-delà, tu obtiens des pages vides.

1import time
2def scrape_hn_pages(num_pages=5):
3    """Scrape plusieurs pages de sujets de la page d’accueil HN."""
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"Page {page}: no stories found, stopping.")
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"Page {page}: scraped {len(story_rows)} stories")
23        # Respecter le délai de crawl de 30 secondes indiqué dans robots.txt
24        if page < num_pages:
25            time.sleep(30)
26    return all_stories
27stories = scrape_hn_pages(5)
28print(f"\nTotal stories scraped: {len(stories)}")

Ce time.sleep(30) est important. Le de HN demande explicitement un délai de crawl de 30 secondes. Si tu l’ignores, tu risques d’être limité en requêtes (HTTP 429) ou temporairement bloqué. Cinq pages à 30 secondes d’intervalle prennent environ 2,5 minutes — pas instantané, mais respectueux.

Pour ceux qui ne veulent pas gérer la pagination en code, gère automatiquement la pagination par clic et le scroll infini. Il clique sur le bouton « More » en bas des pages HN sans aucune configuration.

Accéder aux données historiques Hacker News avec l’API Algolia

L’API Firebase fournit les données actuelles. Pour l’analyse historique — « Quels étaient les meilleurs sujets Python en 2023 ? » ou « Comment la couverture de l’IA a-t-elle évolué sur les 5 dernières années ? » — il faut utiliser .

1import requests
2ALGOLIA_BASE = "https://hn.algolia.com/api/v1"
3> This paragraph contains content that cannot be parsed and has been skipped.
4# Exemple : trouver des sujets de scraping Python avec 10+ points depuis janvier 2024
5results = search_hn(
6    query="python scraping",
7    tags="story",
8)
9print(f"Found {results['nbHits']} total results")
10for hit in results["hits"][:5]:
11    print(f"  [{hit.get('points', 0)} pts] {hit['title']}")

Pour les requêtes filtrées par date, utilise numericFilters :

1import calendar, datetime
2# Sujets depuis le 1er janvier 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.
6L’API Algolia est rapide (5 à 9 ms de temps de traitement serveur), ne nécessite aucune clé API et prend en charge la pagination jusqu’à 500 pages. Pour l’analyse historique en volume, c’est la meilleure option disponible.
7## Exporter les données Hacker News scrapées vers CSV, Excel et Google Sheets
8Tous les tutos de scraping HN que j’ai vus se terminent par un `pprint()` dans le terminal. C’est bien pour déboguer, mais si tu construis un récap quotidien ou que tu fais de l’analyse de tendances, il faut mettre les données dans un fichier. Voici comment faire.
9### Exporter en CSV avec Python
10```python
11import csv
12def export_to_csv(stories, filename="hn_stories.csv"):
13    """Enregistre les sujets scrapés dans un fichier CSV."""
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"Saved {len(stories)} stories to {filename}")
20export_to_csv(stories)

Exporter en Excel avec Python

1import pandas as pd
2def export_to_excel(stories, filename="hn_stories.xlsx"):
3    """Enregistre les sujets scrapés dans un fichier Excel."""
4    df = pd.DataFrame(stories)
5    df.to_excel(filename, index=False, engine="openpyxl")
6    print(f"Saved {len(stories)} stories to {filename}")
7export_to_excel(stories)

Assure-toi que openpyxl est installé — pandas l’utilise comme moteur Excel. S’il manque, tu auras une ImportError.

Envoyer vers Google Sheets (optionnel)

Pour des workflows automatisés, tu peux envoyer les données directement vers Google Sheets avec la bibliothèque gspread. Ça demande de configurer un compte de service Google Cloud une seule fois :

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

L’alternative sans code pour l’export

Si configurer des comptes de service et écrire du code d’export te paraît plus pénible que le scraping lui-même, je comprends. Chez Thunderbit, nous avons créé un export de données gratuit qui te permet d’envoyer les données scrapées directement vers Excel, Google Sheets, Airtable ou Notion — sans code, sans identifiants, sans pipeline à maintenir. Pour une extraction ponctuelle, c’est franchement plus rapide. J’y reviens juste après.

Rendre votre scraper prêt pour la production : gestion d’erreurs, cache et planification

Si tu lances un scraper une seule fois pour le fun, le code ci-dessus suffit. Si tu l’exécutes chaque jour dans un workflow, il te faut quelques briques en plus.

Gestion d’erreurs et logique de retry

Les réseaux tombent en panne. Les serveurs limitent le trafic. Une seule requête ratée ne devrait pas faire planter tout ton scraping. Voici une fonction de retry avec backoff exponentiel :

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    """Récupère une URL avec retries automatiques et backoff exponentiel."""
6    response = requests.get(url, timeout=10)
7    response.raise_for_status()
8    return response
9# Utilisation :
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"Failed after retries: {e}")

La bibliothèque tenacity gère proprement la logique de retry. Elle réessaie jusqu’à 5 fois avec un backoff exponentiel jitteré — en commençant à 1 seconde et en allant jusqu’à 60 secondes. Ça gère bien les erreurs HTTP 429 (limite atteinte), 503 (service indisponible) et les soucis réseau transitoires.

Mettre les réponses en cache pour éviter de rescaper

Pendant le développement, tu relanceras souvent ton scraper en ajustant la logique de parsing. Sans cache, chaque exécution recontacte à nouveau les serveurs HN pour les mêmes données. La bibliothèque requests-cache règle ça en deux lignes :

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

Une fois ces lignes ajoutées en haut de ton script, tous les appels requests.get() sont automatiquement mis en cache dans une base SQLite locale. Relance ton script 10 fois en une heure, et seule la première exécution utilisera le réseau. C’est un outil souvent recommandé , et pour de bonnes raisons.

Séparer le crawl du parsing

Une bonne pratique que les scrapers expérimentés recommandent : télécharger d’abord les données brutes, puis les parser ensuite. Comme ça, si ta logique de parsing a un bug, tu peux la corriger et retraiter sans tout retélécharger.

1import os, json
2def crawl_and_save(story_ids, output_dir="raw_data"):
3    """Récupère les données des sujets et enregistre le JSON brut sur disque."""
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  # Ignorer les éléments déjà récupérés
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.
13Cette approche en deux phases est particulièrement utile quand tu scrapes des centaines d’éléments et que tu veux itérer vite sur la manière de traiter les données.
14### Automatiser votre scraper sur un calendrier
15Pour un digest HN quotidien, ton scraper doit tourner automatiquement. Deux options courantes :
16**Option 1 : cron (Linux/Mac)**
17```bash
18# Exécuter chaque jour à 8h30 UTC
1930 8 * * * /usr/bin/python3 /home/user/scrape_hn.py >> /home/user/scrape.log 2>&1

Option 2 : GitHub Actions (gratuit, pas besoin de serveur)

1name: Scrape Hacker News
2on:
3  schedule:
4    - cron: '30 8 * * *'  # Tous les jours à 8h30 UTC
5  workflow_dispatch:        # Bouton de lancement manuel
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

Quelques pièges à connaître avec la planification GitHub Actions : tous les horaires cron sont en UTC, les retards de 15 à 60 minutes sont fréquents (utilise plutôt des minutes décalées comme :30 que :00), et GitHub peut désactiver les workflows planifiés sur les dépôts inactifs pendant 60 jours. Garde toujours workflow_dispatch pour pouvoir lancer manuellement pendant les tests.

Pour une option plus simple, la fonctionnalité Scheduled Scraper de Thunderbit te permet de décrire la planification en langage naturel — par exemple « scraper tous les matins à 8h » — sans serveur ni configuration cron.

Quand Python devient excessif : la méthode sans code pour scraper Hacker News

Je vais être franc, même si je suis enthousiaste à propos de Python et que mon équipe construit des outils pour développeurs. Si tu as juste besoin des 100 meilleurs sujets HN du jour dans un tableur — maintenant, une seule fois — écrire, déboguer et lancer un script Python est une surcharge inutile. Rien que la configuration (environnement virtuel, installation des paquets, compréhension des sélecteurs) prend plus de temps que la collecte elle-même.

C’est là que entre en jeu. Voici le flux de travail :

  1. Ouvre news.ycombinator.com dans Chrome
  2. Clique sur l’icône de l’extension Thunderbit, puis sur « AI Suggest Fields »
  3. L’IA lit la page et propose les colonnes : Titre, URL, Score, Auteur, Nombre de commentaires, Heure de publication
  4. Ajuste les champs si besoin (renommer, supprimer ou ajouter des champs personnalisés — tu peux même ajouter une consigne IA comme « Classer en IA/Outils Dev/Web/Autre »)
  5. Clique sur « Scrape » — les données apparaissent dans un tableau structuré
  6. Exporte vers Excel, Google Sheets, Airtable ou Notion

Deux clics pour obtenir des données structurées. Aucun sélecteur, aucun code, aucune maintenance.

Un vrai avantage ici : l’IA de Thunderbit s’adapte automatiquement aux changements de mise en page. Les scrapers CSS classiques cassent quand un site modifie son balisage — et même si le HTML de HN est relativement stable, il a changé (la classe class="athing submission" a été mise à jour, span.titleline a remplacé l’ancien a.storylink). Un scraper alimenté par l’IA relit la page à chaque fois, donc il n’est pas sensible aux changements de noms de classes.

python-vs-thunderbit-comparison.webp

Thunderbit gère aussi la pagination (en cliquant automatiquement sur le bouton « More » de HN) et le scraping des sous-pages (en visitant la page de commentaires de chaque sujet pour récupérer les discussions). Pour le cas d’usage de , c’est l’équivalent du code récursif de la méthode 2 — sans écrire une seule ligne.

Le compromis est simple : Python est le bon choix quand tu as besoin de logique personnalisée, de transformations complexes, de pipelines automatisés planifiés, ou si tu es en phase d’apprentissage. Thunderbit est le bon choix quand tu veux des données rapidement, sans maintenance de code, ou si tu n’es pas développeur. Choisis l’outil adapté à ta situation.

Python vs API vs sans code : quelle méthode choisir ?

Voici le cadre de décision complet :

CritèreBeautifulSoup (HTML)API FirebaseAPI AlgoliaThunderbit (sans code)
Compétence technique requisePython intermédiairePython débutantPython débutantAucune
Temps de configuration10–15 min5–10 min5–10 min2 min
Charge de maintenanceMoyenne (les sélecteurs cassent)Faible (JSON stable)Faible (JSON stable)Aucune
Profondeur des donnéesPage d’accueil uniquementN’importe quel item, utilisateursRecherche + historiquePage d’accueil + sous-pages
CommentairesDifficileFacile (récursif)Facile (arbre imbriqué)Scraping des sous-pages
Données historiquesNonNonOui (archive complète)Non
Options d’exportÀ coder soi-mêmeÀ coder soi-mêmeÀ coder soi-mêmeIntégré (Excel, Sheets, etc.)
Planificationcron / GitHub Actionscron / GitHub Actionscron / GitHub ActionsPlanificateur intégré
Idéal pourApprendre le scrapingPipelines fiablesRecherche et analyseCollecte rapide de données

Si tu apprends Python ou que tu construis quelque chose de personnalisé, choisis la méthode 1 ou 2. Si tu as besoin d’analyse historique, ajoute l’API Algolia. Si tu veux juste les données sans le code, .

Conclusion et points clés à retenir

Voici ce que tu as maintenant dans ta boîte à outils :

  • Deux méthodes Python complètes pour scraper Hacker News — BeautifulSoup pour l’analyse HTML et l’API Firebase pour des données JSON propres
  • Des techniques de pagination pour aller au-delà de la page 1, y compris l’API Algolia pour des données historiques remontant à 2007
  • Du code d’export vers CSV, Excel et Google Sheets — parce que des données dans un terminal ne servent à personne d’autre dans ton équipe
  • Des bonnes pratiques production — logique de retry, cache, séparation crawl/parsing et automatisation planifiée via cron ou GitHub Actions
  • Une alternative sans code pour les cas où Python est plus un outil de trop que ce dont tu as besoin

Ma recommandation : commence par l’API Firebase (méthode 2) pour la plupart des usages. C’est plus propre, plus fiable, et ça donne accès aux commentaires sans la complexité du parsing HTML imbriqué. Ajoute l’API Algolia quand tu as besoin d’historique. Et garde dans tes favoris pour les moments où tu veux juste un tableur rapide sans monter tout un projet Python.

Si tu veux aller plus loin, essaie de scraper les commentaires HN pour faire de , construis un pipeline de digest quotidien avec GitHub Actions, ou explore l’API Algolia pour suivre l’évolution des tendances technologiques sur la dernière décennie.

Essayez Thunderbit pour un scraping rapide de Hacker News

FAQ

Est-il légal de scraper Hacker News ?

Les données de HN sont publiques, et Y Combinator fournit une API officielle précisément pour l’accès programmatique. Le du site autorise le scraping du contenu en lecture seule (page d’accueil, pages d’items, pages utilisateurs) mais demande un délai de crawl de 30 secondes. Respecte ce délai, ne scrape pas les endpoints interactifs (votes, connexion), et tu es sur une base solide. Pour en savoir plus sur l’éthique du scraping, consulte notre guide sur les .

Hacker News a-t-il une API officielle ?

Oui. L’ à l’adresse hacker-news.firebaseio.com/v0/ est gratuite, ne nécessite aucune authentification et donne accès aux sujets, commentaires, profils utilisateurs et à tous les types de flux (top, new, best, ask, show, jobs). Elle renvoie du JSON propre et n’affiche pas de limite de requêtes explicite, même s’il est toujours conseillé de rester raisonnable dans la fréquence des appels.

Comment scraper les commentaires Hacker News avec Python ?

Avec l’API Firebase, récupère un sujet pour obtenir son champ kids (un tableau d’IDs de commentaires de premier niveau). Chaque commentaire est lui-même un item avec son propre champ kids pour les réponses. Parcours l’arbre récursivement avec une fonction qui récupère chaque commentaire et ses enfants. Voir la section « Scraper les commentaires (parcours récursif de l’arbre) » ci-dessus pour le code complet. Sinon, l’endpoint /items/<id> de renvoie l’arbre complet des commentaires imbriqués en une seule requête — beaucoup plus rapide pour les sujets très commentés.

Peut-on scraper Hacker News sans écrire de code ?

Oui. fonctionne comme une extension Chrome : ouvre HN, clique sur « AI Suggest Fields » et il identifie automatiquement des colonnes comme le titre, l’URL, le score et l’auteur. Clique sur « Scrape » et exporte directement vers Excel, Google Sheets, Airtable ou Notion. Il gère la pagination et peut même visiter les sous-pages pour récupérer les commentaires. Pas de Python, pas de sélecteurs, pas de maintenance.

Comment obtenir des données historiques de Hacker News ?

L’ est le meilleur outil pour ça. Utilise l’endpoint search_by_date avec numericFilters=created_at_i>TIMESTAMP pour filtrer par plage de dates. Tu peux rechercher par mot-clé, filtrer par type de sujet et paginer jusqu’à 500 pages de résultats. Pour une analyse historique massive, des jeux de données publics sont aussi disponibles sur (archive complète), (28 millions d’enregistrements) et (4 millions de sujets).

En savoir plus

Shuai Guan
Shuai Guan
Co-founder/CEO @ Thunderbit. Passionate about cross section of AI and Automation. He's a big advocate of automation and loves making it more accessible to everyone. Beyond tech, he channels his creativity through a passion for photography, capturing stories one picture at a time.
Table des matières

Essaie Thunderbit

Extrayez des leads et d’autres données en seulement 2 clics. Propulsé par l’IA.

Obtenir Thunderbit C’est gratuit
Extraire des données grâce à l’IA
Transfère facilement les données vers Google Sheets, Airtable ou Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week