Python ile Hacker News Nasıl Kazınır? (2 Yöntem, Tüm Kodlarla)

Son güncelleme: August 20, 2026
Python ile Hacker News Nasıl Kazınır? (2 Yöntem, Tüm Kodlarla)

Birkaç ay önce Thunderbit ekibi için her gün en popüler Hacker News hikâyelerinden oluşan bir özet hazırlamak istedim. İlk dürtüm siteyi yer imlerine ekleyip her sabah hızlıca göz atmaktı. Bu yöntem yaklaşık üç gün sürdü; sonra sadece başlıkları okumak ve bağlantıları bir tabloya kopyalamak için günde 20 dakika harcadığımı fark ettim.

Hacker News, internet üzerindeki en zengin ve en yoğun teknoloji istihbaratı kaynaklarından biri — aylık yaklaşık 13 milyon ziyaret, her gün gönderilen yaklaşık 1.300 yeni hikâye ve günlük yaklaşık 13.000 yorum. İster yükselen teknoloji trendlerini takip edin, ister markanızı izleyin, ister "Who’s Hiring" başlıklarından işe alım havuzu oluşturun, ister geliştirici dünyasının neye önem verdiğini anlamaya çalışın; bunların hepsini elle takip etmeye çalışmak kaybedilmiş bir savaş.

İyi haber şu: Python ile Hacker News kazımak şaşırtıcı derecede kolay. Bu rehberde size iki eksiksiz yöntemi anlatacağım — BeautifulSoup ile HTML kazıma ve resmi HN Firebase API’si — ayrıca sayfalama, veri dışa aktarma, üretime hazır kullanım kalıpları ve Python fazla geliyorsa kullanabileceğiniz kodsuz bir kısa yol da göstereceğim.

Neden Hacker News’i Python ile Kazımalısınız?

Hacker News sıradan bir bağlantı toplayıcı değil. Oylar ve aktif tartışmalar sayesinde en ilgi çekici teknoloji hikâyelerinin öne çıktığı, topluluk odaklı ve özenle seçilmiş bir akış. Kitlesi büyük ölçüde teknoloji profesyonellerinden oluşur (yaklaşık yüzde 76 erkek, ana yaş grubu 25–34); sitenin yüzde 66’lık doğrudan trafik oranı da bunun tesadüfi bir ziyaretçi kitlesi değil, düzenli ve sadık bir okur topluluğu olduğunu gösterir.

HN verilerini kazımak için başlıca nedenler şunlar:

Kullanım SenaryosuElde Edeceğiniz Sonuç
Günlük teknoloji özetiEn popüler hikâyeler, puanlar ve bağlantılar e-posta ya da Slack’e gelir
Marka / rakip takibiŞirketiniz ya da ürününüz geçtiğinde uyarı alırsınız
Trend analiziHangi teknolojilerin, dillerin veya konuların zaman içinde ivme kazandığını izlersiniz
İşe alım"Who’s Hiring" başlıklarını iş ilanları, teknoloji yığınları ve maaş sinyalleri için ayrıştırırsınız
İçerik araştırmasıHakkında yazılacak veya paylaşılacak yüksek performanslı konular bulursunuz
Duygu analiziTopluluğun ürünler, lansmanlar veya sektör değişimleri hakkındaki görüşünü ölçersiniz

Toplam piyasa değeri 400 milyar doları aşan şirketler — Stripe, Dropbox, Airbnb — ilk geri bildirimlerinin ve kullanıcılarının önemli bir kısmını Hacker News’e borçlu. Drew Houston, Dropbox demosunu Nisan 2007’de HN’de paylaştı; gönderi #1’e yükseldi ve beta bekleme listesi tek bir günde 5.000 kullanıcıdan 75.000 kullanıcıya fırladı. HN verisi sadece ilginç değil — aynı zamanda ticari açıdan da çok değerli.

Veri herkese açık, ama sitenin yapısı manuel toplamayı zahmetli hale getiriyor. Pratik çözüm: Python ile otomasyon.

Hacker News’i Python ile Kazımanın İki Yolu: Genel Bakış

Bu rehber, çalıştırılabilir iki eksiksiz yaklaşımı kapsıyor:

  1. requests + BeautifulSoup ile HTML kazıma — news.ycombinator.com’un ham HTML’ini çekip hikâye verilerini ayıklamak için ayrıştırır. Kazıma temellerini öğrenmek ve sayfada görünenleri birebir almak için idealdir.
  2. Resmi Hacker News Firebase API’si — JSON uç noktalarına doğrudan istek atar, HTML ayrıştırmaya gerek kalmaz. Güvenilir veri akışları, yorumlara erişim ve geçmiş veriler için daha uygundur.

Hangisinin size uygun olduğuna karar vermenize yardımcı olmak için yan yana bir karşılaştırma:

KriterHTML Kazıma (requests + BS4)HN Firebase APIThunderbit (Kodsuz)
Kurulum karmaşıklığıOrta (HTML seçicileri ayrıştırma)Düşük (JSON uç noktaları)Yok (2 tıkla Chrome eklentisi)
Veri güncelliğiAna sayfa için gerçek zamanlıGerçek zamanlı (ID ile herhangi bir öğe)Gerçek zamanlı
Rate limit riskiOrta (robots.txt 30 sn crawl gecikmesi ister)Düşük (resmî, cömert)Thunderbit tarafından yönetilir
Yorum erişimiZor (iç içe HTML)Kolay (özyinelemeli öğe ID’leri)Alt sayfa kazıma özelliği
Geçmiş veriSınırlıAlgolia Search API üzerindenYok
En uygun kullanımKazıma temellerini öğrenmeGüvenilir veri akışlarıTeknik olmayan kullanıcılar, hızlı dışa aktarma

Her iki yöntemde de tam ve çalıştırılabilir Python kodu yer alıyor. Hiç kod yazmadan veriyi almak istiyorsanız, onu da anlatacağım.

Başlamadan Önce

  • Zorluk seviyesi: Başlangıç – Orta
  • Gerekli süre: Her yöntem için yaklaşık 15–20 dakika
  • İhtiyacınız olanlar:
    • Python 3.11+ yüklü olmalı
    • Bir terminal veya kod editörü
    • Chrome tarayıcı (HN’nin HTML’ini incelemek veya kodsuz seçeneği denemek isterseniz)
    • Thunderbit Chrome Eklentisi (isteğe bağlı, kodsuz yöntem için)

scrape-hacker-news-methods.webp

Python Ortamınızı Kurma

HN verisine dokunmadan önce ortamı hazırlayalım. Proje bağımlılıklarının temiz kalması için sanal ortam oluşturmanızı öneririm.

# Sanal ortam oluştur ve etkinleştir
python3 -m venv hn-scraper
# macOS/Linux:
source hn-scraper/bin/activate
# Windows:
hn-scraper\Scripts\activate

# Her iki yöntem için gerekli paketleri yükle
pip install requests==2.33.1 beautifulsoup4==4.14.3 pandas==3.0.2 openpyxl==3.1.5

İleride üretim kalıpları için (önbellekleme, yeniden deneme) şunlar da faydalı olur:

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

Özel API anahtarına ya da kimlik doğrulama belirtecine gerek yok. HN verisi açık.

Yöntem 1: BeautifulSoup ile Python Kullanarak Hacker News Kazıma

Bu klasik yöntemdir — HTML’i çek, ayrıştır ve istediğin veriyi al. Çoğu kişi web kazımayı bu şekilde öğrenir; HN’nin sade, tablo tabanlı yapısı da bunu öğrenmek için harika bir zemin sunar.

1. Adım: Hacker News Ana Sayfasını Çek

Editörünüzde scrape_hn_bs4.py adlı bir dosya oluşturun. Başlangıç kodu şöyle:

import requests
from bs4 import BeautifulSoup

url = "https://news.ycombinator.com/news"
headers = {"User-Agent": "Mozilla/5.0 (educational HN scraper)"}
response = requests.get(url, headers=headers)
soup = BeautifulSoup(response.text, "html.parser")

print(f"Status: {response.status_code}, Page length: {len(response.text)} chars")

Çalıştırın. Status: 200 ve yaklaşık 40.000–50.000 karakter uzunluğunda bir sayfa çıktısı görmelisiniz. Bu, HN ana sayfasının ham HTML’i; bellekte duruyor ve ayrıştırılmayı bekliyor.

2. Adım: HTML Yapısını Anlayın

HN, modern CSS grid ya da flexbox yerine tablo tabanlı bir düzen kullanır. Sayfadaki her hikâye iki temel <tr> satırından oluşur:

  • Hikâye satırı (<tr class="athing submission">): sıra numarasını, başlığı ve bağlantıyı içerir
  • Meta veri satırı (hemen sonraki <tr>): puan, yazar, zaman ve yorum sayısını içerir

Önemli seçiciler:

  • span.titleline > a — hikâye başlığı ve URL’si
  • span.score — oy sayısı (ör. "118 points")
  • a.hnuser — yazarın kullanıcı adı
  • span.age — gönderim zamanı
  • .subtext içindeki, metninde "comment" geçen son <a> — yorum sayısı

Chrome’da herhangi bir hikâye başlığına sağ tıklayıp "Inspect" seçerseniz, buna benzer bir yapı görürsünüz:

<span class="titleline">
  <a href="https://darkbloom.dev">Darkbloom – Private inference on idle Macs</a>
</span>

Altındaki meta veri satırı ise şöyle görünür:

<span class="score" id="score_47788542">118 points</span>
by <a href="user?id=twapi" class="hnuser">twapi</a>
<span class="age" title="2026-04-16T04:06:39 1776312399">
  <a href="item?id=47788542">2 hours ago</a>
</span>
| <a href="item?id=47788542">65&nbsp;comments</a>

Bu seçicileri doğru anlamak çok önemlidir — HN bir gün işaretlemesini değiştirirse bu seçimleri güncellemeniz gerekir. (İpucu: API yöntemi bu sorunu tamamen ortadan kaldırır.)

3. Adım: Başlıkları, Bağlantıları ve Puanları Çıkarın

Şimdi asıl işe geçiyoruz. Her hikâye satırını dolaşacak, başlık ve bağlantıyı hikâye satırından alacak, ardından hemen altındaki meta veri satırından puanı çekeceğiz.

import requests
from bs4 import BeautifulSoup
from pprint import pprint

url = "https://news.ycombinator.com/news"
headers = {"User-Agent": "Mozilla/5.0 (educational HN scraper)"}
response = requests.get(url, headers=headers)
soup = BeautifulSoup(response.text, "html.parser")

stories = []
story_rows = soup.select("tr.athing")

for row in story_rows:
    # Hikâye satırından başlık ve URL
    title_tag = row.select_one("span.titleline > a")
    if not title_tag:
        continue
    title = title_tag.get_text()
    link = title_tag.get("href", "")

    # Bir sonraki kardeş satırdan meta veriler
    meta_row = row.find_next_sibling("tr")
    score = 0
    author = ""
    comments = 0

    if meta_row:
        if score_tag := meta_row.select_one("span.score"):
            score = int(score_tag.get_text().replace(" points", ""))
        if author_tag := meta_row.select_one("a.hnuser"):
            author = author_tag.get_text()
        # Yorum sayısı: metninde "comment" geçen son <a>
        for a_tag in meta_row.select("a"):
            text = a_tag.get_text()
            if "comment" in text:
                comments = int(text.split("\xa0")[0])

    stories.append({
        "title": title,
        "url": link,
        "score": score,
        "author": author,
        "comments": comments,
    })

# 50+ puanlı hikâyeleri filtrele, puana göre sırala
top_stories = sorted(
    [s for s in stories if s["score"] >= 50],
    key=lambda x: x["score"],
    reverse=True,
)

pprint(top_stories[:10])

Kodla ilgili birkaç not:

  • Morus operatörü (:=) Python 3.8+ ile çalışır. span.score gibi her satırda bulunmayabilecek isteğe bağlı öğeler için atamayı ve kontrolü tek satırda yapmanızı sağlar.
  • HN, sayı ile "comments" arasında \xa0 (boşluk olmayan karakter) kullanır; bu yüzden ayırırken onu baz alıyoruz.
  • HN içindeki başka sayfalara bağlanan hikâyelerde (örneğin "Ask HN" gönderileri) item?id= ile başlayan göreli URL’ler bulunur. Bunlar için başına https://news.ycombinator.com/ eklemek isteyebilirsiniz.

4. Adım: Çalıştırın ve Sonuçları Görün

Kaydedin ve çalıştırın:

python scrape_hn_bs4.py

Şuna benzer bir çıktı görmelisiniz:

[{'author': 'twapi',
  'comments': 65,
  'score': 118,
  'title': 'Darkbloom – Private inference on idle Macs',
  'url': 'https://darkbloom.dev'},
 {'author': 'sebg',
  'comments': 203,
  'score': 247,
  'title': 'Show HN: I built an open-source Perplexity alternative',
  'url': 'https://github.com/...'},
 ...]

Bu, 1. sayfadaki 30 hikâyedir. Ancak HN’nin her an yüzlerce aktif hikâyesi vardır. Sayfalama konusunu sonraki bölümde anlatacağız.

Yöntem 2: Resmî API ile Python Kullanarak Hacker News Kazıma

HN Firebase API, Hacker News verisine erişmek için resmî olarak desteklenen yoldur. Kimlik doğrulama yok, API anahtarı yok, HTML ayrıştırma yok. Temiz JSON yanıtları alırsınız. Üretimde güvenilir biçimde çalışması gereken işler için bu yöntemi kullanıyorum.

Bilmeniz Gereken Temel API Uç Noktaları

Temel adres https://hacker-news.firebaseio.com/v0/. İşinize yarayacak uç noktalar şunlar:

Uç NoktaDöndürdüğü VeriÖrnek
/v0/topstories.jsonEn fazla 500 en iyi hikâye ID’si dizisi[47788542, 47787901, ...]
/v0/newstories.jsonEn fazla 500 en yeni hikâye ID’siAynı biçim
/v0/beststories.jsonEn fazla 500 en iyi hikâye ID’siAynı biçim
/v0/askstories.jsonEn fazla 200 "Ask HN" hikâye ID’siAynı biçim
/v0/showstories.jsonEn fazla 200 "Show HN" hikâye ID’siAynı biçim
/v0/jobstories.jsonEn fazla 200 iş ilanı hikâye ID’siAynı biçim
/v0/item/{id}.jsonHerhangi bir öğenin tam ayrıntıları (hikâye, yorum, anket)JSON nesnesi
/v0/user/{username}.jsonKullanıcı profiliJSON nesnesi
/v0/maxitem.jsonGeçerli en büyük öğe ID’siTam sayı (ör. 47789427)

Bir hikâye öğesi şöyle görünür:

{
  "by": "twapi",
  "descendants": 65,
  "id": 47788542,
  "kids": [47789171, 47788769, 47788762],
  "score": 118,
  "time": 1776312399,
  "title": "Darkbloom – Private inference on idle Macs",
  "type": "story",
  "url": "https://darkbloom.dev"
}

kids alanı, doğrudan çocuk yorumların ID’lerini içerir. Her yorum da kendi kids alanına sahip bir öğedir — yorum ağacı böyle kurulur.

1. Adım: En İyi Hikâye ID’lerini Çekin

scrape_hn_api.py adlı bir dosya oluşturun:

import requests
import time
from pprint import pprint

API_BASE = "https://hacker-news.firebaseio.com/v0"

# En iyi hikâye ID'lerini çek
response = requests.get(f"{API_BASE}/topstories.json")
story_ids = response.json()

print(f"Got {len(story_ids)} top story IDs")
# Output: Got 500 top story IDs

Tek istekte 500 hikâye ID’si — ayrıştırma yok, seçici yok, sadece bir JSON dizisi.

2. Adım: Hikâye Ayrıntılarını ID’ye Göre Çekin

Şimdi gerçek hikâye verilerine ihtiyacımız var. Burada fan-out sorunu ortaya çıkıyor: 500 hikâye, 500 ayrı API çağrısı demek. Yaptığım ölçümlerde, her öğe isteği sıralı biçimde yaklaşık 1.2 saniye sürüyor. 500 hikâye için bu yaklaşık 10 dakika eder.

Çoğu kullanım için 500’üne ihtiyacınız yok. İşte ilk 30 hikâyeyi çekmek için kod:

def fetch_story(story_id):
    """HN API'den tek bir hikâyenin ayrıntılarını getirir."""
    resp = requests.get(f"{API_BASE}/item/{story_id}.json")
    return resp.json()

# İlk 30 hikâyenin ayrıntılarını çek
stories = []
for sid in story_ids[:30]:
    story = fetch_story(sid)
    if story and story.get("type") == "story":
        stories.append({
            "title": story.get("title", ""),
            "url": story.get("url", ""),
            "score": story.get("score", 0),
            "author": story.get("by", ""),
            "comments": story.get("descendants", 0),
            "time": story.get("time", 0),
            "id": story.get("id"),
        })
    time.sleep(0.1)  # Nazik ol — istekler arasında kısa bekleme

# Puanına göre sırala, ilk 10'u göster
top = sorted(stories, key=lambda x: x["score"], reverse=True)[:10]
pprint(top)

time.sleep(0.1) küçük bir nezaket gecikmesi ekler. Firebase API için belirtilmiş bir rate limit yok, ama herhangi bir API’yi duraksız bombardımana tutmak iyi bir uygulama değildir.

3. Adım: Yorumları Kazıyın (Özyinelemeli Ağaç Gezimi)

İşte API’nin HTML kazımaya göre gerçekten parladığı yer burası. HN’deki yorumlar çok katmanlıdır — yanıtların yanıtları, onların da yanıtları… HTML’de bu, karmaşık iç içe tablo yapılarıyla uğraşmak demektir. API’de ise her yorumun kids alanı çocuklarının ID’lerini verir; siz de ağacı özyinelemeli olarak gezersiniz.

def fetch_comments(item_id, depth=0, max_depth=3):
    """max_depth'e kadar yorumları özyinelemeli olarak getirir."""
    item = requests.get(f"{API_BASE}/item/{item_id}.json").json()
    if not item or item.get("type") != "comment":
        return []

    comments = [{
        "author": item.get("by", "[silinmiş]"),
        "text": item.get("text", ""),
        "depth": depth,
        "id": item.get("id"),
    }]

    if depth < max_depth and item.get("kids"):
        for kid_id in item["kids"]:
            comments.extend(fetch_comments(kid_id, depth + 1, max_depth))
            time.sleep(0.05)

    return comments

# Örnek: en üstteki hikâyenin yorumlarını çek
if stories:
    top_story = stories[0]
    top_story_full = requests.get(f"{API_BASE}/item/{top_story['id']}.json").json()
    if top_story_full.get("kids"):
        print(f"\nComments for: {top_story['title']}")
        all_comments = []
        for kid_id in top_story_full["kids"][:5]:  # İlk 5 üst seviye yorum
            all_comments.extend(fetch_comments(kid_id, depth=0, max_depth=2))
            time.sleep(0.1)

        for c in all_comments[:15]:
            indent = "  " * c["depth"]
            preview = c["text"][:80].replace("\n", " ") if c["text"] else "[metin yok]"
            print(f"{indent}[{c['author']}] {preview}...")

Bu özyinelemeli yaklaşım, iç içe geçmiş HTML yorum zincirlerini ayrıştırmaya çalışmaktan çok daha kolaydır. Tam yorum ağaçlarına ihtiyacınız varsa, doğru yöntem API’dir.

4. Adım: Çalıştırın ve Sonuçları Görün

python scrape_hn_api.py

Yapılandırılmış hikâye verileriyle başlayan ve ardından iç içe bir yorum önizlemesi gösteren bir çıktı göreceksiniz. Veri daha temizdir, yorumlara erişim çok daha kolaydır ve HN bir CSS sınıf adını değiştirdi diye kazıyıcınızın bozulma riski yoktur.

1. Sayfanın Ötesine Geçmek: Sayfalama ve Geçmiş Veri

Çoğu HN kazıma rehberi 1. sayfada — yani 30 hikâyede — durur. Hızlı bir demo için bu yeterli olabilir, ancak gerçek kullanım senaryoları genellikle daha fazlasını ister.

BeautifulSoup ile Birden Fazla Sayfayı Kazımak

HN’nin sayfalama yapısı basittir: ?p=2, ?p=3 gibi bir URL deseni kullanır. Her sayfa 30 hikâye getirir ve site yaklaşık 20. sayfaya kadar veri sunar (toplamda yaklaşık 600 hikâye). Bundan sonrası boş sayfalar döner.

import time

def scrape_hn_pages(num_pages=5):
    """HN ana sayfasının birden fazla sayfasını kazır."""
    all_stories = []

    for page in range(1, num_pages + 1):
        url = f"https://news.ycombinator.com/news?p={page}"
        response = requests.get(url, headers=headers)
        soup = BeautifulSoup(response.text, "html.parser")

        story_rows = soup.select("tr.athing")
        if not story_rows:
            print(f"Page {page}: no stories found, stopping.")
            break

        for row in story_rows:
            title_tag = row.select_one("span.titleline > a")
            if not title_tag:
                continue
            meta_row = row.find_next_sibling("tr")
            score = 0
            if meta_row and (score_tag := meta_row.select_one("span.score")):
                score = int(score_tag.get_text().replace(" points", ""))

            all_stories.append({
                "title": title_tag.get_text(),
                "url": title_tag.get("href", ""),
                "score": score,
            })

        print(f"Page {page}: scraped {len(story_rows)} stories")

        # robots.txt'deki 30 saniyelik crawl gecikmesine saygı göster
        if page < num_pages:
            time.sleep(30)

    return all_stories

stories = scrape_hn_pages(5)
print(f"\nTotal stories scraped: {len(stories)}")

Bu time.sleep(30) kısmı önemlidir. HN’nin robots.txt dosyası açıkça 30 saniyelik crawl gecikmesi talep eder. Bunu yok sayarsanız rate limit’e takılabilir (HTTP 429) veya geçici olarak engellenebilirsiniz. Beş sayfayı 30 saniyelik aralıklarla çekmek yaklaşık 2.5 dakika sürer — anlık değil ama saygılıdır.

Sayfalama koduyla uğraşmak istemeyen kullanıcılar için Thunderbit, tıklamalı ve sonsuz kaydırmalı sayfalamayı otomatik olarak yönetir. HN sayfalarının altındaki "More" düğmesine hiçbir ayar yapmadan tıklar.

Yapay Zeka ile Hacker News Sayfalarını Kazı

Algolia API ile Geçmiş Hacker News Verilerine Erişmek

Firebase API size güncel veriyi verir. Geçmiş analiz için — "2023’te en iyi Python hikâyeleri nelerdi?" veya "Son 5 yılda yapay zekâ kapsamı nasıl değişti?" gibi sorular için — HN Algolia Search API gerekir.

import requests

ALGOLIA_BASE = "https://hn.algolia.com/api/v1"

def search_hn(query, tags="story", page=0, hits_per_page=20):
    """Algolia API üzerinden HN'de arama yapar."""
    params = {
        "query": query,
        "tags": tags,
        "page": page,
        "hitsPerPage": hits_per_page,
    }
    resp = requests.get(f"{ALGOLIA_BASE}/search", params=params)
    return resp.json()

# Örnek: Ocak 2024'ten beri 10+ puanlı Python kazıma hikâyelerini bul
results = search_hn(
    query="python scraping",
    tags="story",
)
print(f"Found {results['nbHits']} total results")

for hit in results["hits"][:5]:
    print(f"  [{hit.get('points', 0)} pts] {hit['title']}")

Tarihe göre filtreleme için numericFilters kullanın:

import calendar, datetime

# 1 Ocak 2024 sonrası hikâyeler
start_date = datetime.datetime(2024, 1, 1)
start_ts = int(calendar.timegm(start_date.timetuple()))

params = {
    "query": "python web scraping",
    "tags": "story",
    "numericFilters": f"created_at_i>{start_ts},points>10",
    "hitsPerPage": 50,
}
resp = requests.get(f"{ALGOLIA_BASE}/search_by_date", params=params)
data = resp.json()
print(f"Found {data['nbHits']} stories about Python web scraping since 2024 with >10 points")

Algolia API hızlıdır (sunucu işlem süresi 5–9 ms), API anahtarı gerektirmez ve 500 sayfaya kadar sayfalama destekler. Toplu geçmiş analiz için mevcut en iyi seçenektir.

Kazınan Hacker News Verisini CSV, Excel ve Google Sheets’e Aktarmak

Gördüğüm hemen her HN kazıma rehberi terminalde pprint() çıktısıyla bitiyor. Hata ayıklama için güzel, ama günlük özet ya da trend analizi yapıyorsanız veriyi bir dosyaya aktarmanız gerekir. Bunu nasıl yapacağınız aşağıda.

Python ile CSV’ye Aktarma

import csv

def export_to_csv(stories, filename="hn_stories.csv"):
    """Kazınan hikâyeleri CSV dosyasına kaydeder."""
    fieldnames = ["title", "url", "score", "author", "comments"]
    with open(filename, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=fieldnames)
        writer.writeheader()
        writer.writerows(stories)
    print(f"Saved {len(stories)} stories to {filename}")

export_to_csv(stories)

Python ile Excel’e Aktarma

import pandas as pd

def export_to_excel(stories, filename="hn_stories.xlsx"):
    """Kazınan hikâyeleri Excel dosyasına kaydeder."""
    df = pd.DataFrame(stories)
    df.to_excel(filename, index=False, engine="openpyxl")
    print(f"Saved {len(stories)} stories to {filename}")

export_to_excel(stories)

openpyxl paketinin kurulu olduğundan emin olun — pandas Excel motoru olarak onu kullanır. Eksikse ImportError alırsınız.

Google Sheets’e Aktarma (İsteğe Bağlı)

Otomatik iş akışları için gspread kütüphanesini kullanarak veriyi doğrudan Google Sheets’e göndermek isteyebilirsiniz. Bunun için Google Cloud service account kurulumu gerekir (tek seferlik bir işlem):

import gspread

gc = gspread.service_account(filename="service_account.json")
sh = gc.open("HN Daily Digest")
worksheet = sh.sheet1

# Hikâyeleri satırlara dönüştür
header = list(stories[0].keys())
rows = [list(s.values()) for s in stories]

worksheet.clear()
worksheet.update([header] + rows)
print("Pushed to Google Sheets")

Kodsuz Dışa Aktarma Alternatifi

Service account kurmak ve dışa aktarma kodu yazmak, gerçek kazımadan daha fazla iş gibi geliyorsa sizi anlıyorum. Thunderbit’te, kazınan veriyi doğrudan Excel, Google Sheets, Airtable veya Notion’a göndermenizi sağlayan ücretsiz veri dışa aktarma özelliği geliştirdik — kod yok, kimlik bilgisi yok, bakım gerektiren bir veri hattı yok. Tek seferlik veri çekimleri için gerçekten daha hızlıdır. Aşağıda daha fazla bilgi var.

Kazıyıcınızı Üretime Hazır Hale Getirme: Hata Yönetimi, Önbellekleme ve Zamanlama

Kazıyıcıyı sadece eğlence için bir kez çalıştırıyorsanız yukarıdaki kod yeterlidir. Ama bunu bir iş akışının parçası olarak her gün çalıştıracaksanız birkaç parça daha gerekir.

Hata Yönetimi ve Yeniden Deneme Mantığı

Ağlar hata verir. Sunucular isteği sınırlar. Tek bir hatalı istek tüm kazıma işlemini çökertmemeli. İşte üstel geri çekilme kullanan bir yeniden deneme fonksiyonu:

from tenacity import retry, stop_after_attempt, wait_exponential_jitter
import requests

@retry(stop=stop_after_attempt(5), wait=wait_exponential_jitter(initial=1, max=60))
def fetch_with_retry(url):
    """Bir URL'yi otomatik yeniden deneme ve üstel geri çekilme ile getirir."""
    response = requests.get(url, timeout=10)
    response.raise_for_status()
    return response

# Kullanım:
try:
    resp = fetch_with_retry("https://hacker-news.firebaseio.com/v0/topstories.json")
    story_ids = resp.json()
except Exception as e:
    print(f"Failed after retries: {e}")

tenacity kütüphanesi yeniden deneme mantığını temiz biçimde yönetir. 1 saniyeden başlayıp 60 saniyeye kadar çıkan, rastgeleleştirilmiş üstel geri çekilme ile en fazla 5 kez tekrar dener. Bu yaklaşım HTTP 429 (rate limit), 503 (servis kullanılamıyor) ve geçici ağ hatalarını nazikçe ele alır.

Yeniden Kazımayı Önlemek İçin Yanıtları Önbelleğe Alma

Geliştirme sırasında ayrıştırma mantığını düzeltirken kazıyıcıyı birçok kez çalıştırırsınız. Önbellek yoksa her çalıştırma HN sunucularına aynı veriler için yeniden istek gönderir. requests-cache bunu iki satırda çözer:

import requests_cache

requests_cache.install_cache("hn_cache", expire_after=3600)  # 1 saat önbellek

Bu satırları betiğinizin üstüne ekledikten sonra tüm requests.get() çağrıları yerel bir SQLite veritabanında otomatik olarak önbelleğe alınır. Betiği bir saat içinde 10 kez yeniden çalıştırırsanız, ağ isteklerini yalnızca ilk çalıştırma yapar. Bu, forum kullanıcılarının sıkça önerdiği bir araçtır ve bunun iyi bir nedeni vardır.

Tarama ve Ayrıştırmayı Birbirinden Ayırmak

Deneyimli kazıyıcıların çok sevdiği bir kalıp: önce ham veriyi indir, sonra ayrıştır. Böylece ayrıştırma mantığınızda bir hata olursa, yeniden indirmeden düzeltebilir ve tekrar ayrıştırabilirsiniz.

import os, json

def crawl_and_save(story_ids, output_dir="raw_data"):
    """Hikâye verisini çeker ve ham JSON'u diske kaydeder."""
    os.makedirs(output_dir, exist_ok=True)
    for sid in story_ids:
        filepath = os.path.join(output_dir, f"{sid}.json")
        if os.path.exists(filepath):
            continue  # Daha önce çekilen öğeleri atla
        resp = fetch_with_retry(f"{API_BASE}/item/{sid}.json")
        with open(filepath, "w") as f:
            json.dump(resp.json(), f)

def parse_saved_data(input_dir="raw_data"):
    """Kaydedilmiş JSON dosyalarını yapılandırılmış hikâye listesine dönüştürür."""
    stories = []
    for filename in os.listdir(input_dir):
        with open(os.path.join(input_dir, filename)) as f:
            item = json.load(f)
        if item and item.get("type") == "story":
            stories.append({
                "title": item.get("title", ""),
                "url": item.get("url", ""),
                "score": item.get("score", 0),
                "author": item.get("by", ""),
                "comments": item.get("descendants", 0),
            })
    return stories

Bu iki aşamalı yaklaşım, yüzlerce öğe kazırken ve veriyi nasıl işlediğinizi hızlıca denemek istediğinizde özellikle değerlidir.

Kazıyıcınızı Zamanlayarak Otomatik Çalıştırma

Günlük bir HN özeti için kazıyıcının otomatik çalışması gerekir. Yaygın iki seçenek:

Seçenek 1: cron (Linux/Mac)

# Her gün UTC 08:30'da çalıştır
30 8 * * * /usr/bin/python3 /home/user/scrape_hn.py >> /home/user/scrape.log 2>&1

Seçenek 2: GitHub Actions (ücretsiz, sunucu gerektirmez)

name: Scrape Hacker News

on:
  schedule:
    - cron: '30 8 * * *'  # Her gün UTC 08:30
  workflow_dispatch:        # Manuel çalıştırma düğmesi

jobs:
  scrape:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v6
        with:
          python-version: '3.12'
      - run: pip install requests beautifulsoup4 pandas openpyxl
      - run: python scrape_hn.py
      - run: |
          git config user.name "GitHub Actions Bot"
          git config user.email "actions@github.com"
          git add -A
          git diff --staged --quiet || git commit -m "Update HN data $(date -u +%Y-%m-%dT%H:%M:%SZ)"
          git push

GitHub Actions zamanlamasında birkaç önemli nokta var: Tüm cron saatleri UTC’dir, 15–60 dakikalık gecikmeler yaygındır (bu yüzden :00 yerine :30 gibi ara saatler kullanın) ve GitHub, 60 gün boyunca etkinlik olmayan depolarda planlı iş akışlarını devre dışı bırakabilir. Test için manuel tetikleme yapabilmek adına mutlaka workflow_dispatch ekleyin.

Daha basit bir seçenek olarak, Thunderbit’in Scheduled Scraper özelliği size sunucu ya da cron kurmadan, "her sabah 8’de kazı" gibi düz İngilizce ifadelerle zamanlama tanımlama imkânı verir.

Python Fazla Geldiğinde: Hacker News’i Kodsuz Kazıma Yolu

Burada dürüst olacağım; ben Python meraklısıyım ve ekibim geliştirici araçları üretiyor olsa da. Eğer bugünlük en popüler 100 HN hikâyesini tek seferlik olarak bir tabloya almak istiyorsanız, Python scripti yazmak, hata ayıklamak ve çalıştırmak gereksiz bir yük olabilir. Kurulumun kendisi bile (sanal ortam, paket yükleme, seçicileri çözme) asıl veri toplamadan daha uzun sürebilir.

İşte Thunderbit tam burada devreye giriyor. İş akışı şöyle:

  1. Chrome’da news.ycombinator.com sayfasını açın
  2. Thunderbit eklenti simgesine tıklayın, ardından "AI Suggest Fields" seçeneğini kullanın
  3. Yapay zekâ sayfayı okur ve şu sütunları önerir: Başlık, URL, Puan, Yazar, Yorum Sayısı, Gönderim Zamanı
  4. İsterseniz alanları düzenleyin (yeniden adlandırın, kaldırın veya özel alan ekleyin — hatta "AI/DevTools/Web/Other olarak sınıflandır" gibi bir AI istemi bile ekleyebilirsiniz)
  5. "Scrape" düğmesine tıklayın — veri yapılandırılmış bir tablo halinde görünür
  6. Excel, Google Sheets, Airtable veya Notion’a aktarın

Yapılandırılmış veriye iki tıkla ulaşırsınız. Seçici yok, kod yok, bakım yok.

Buradaki gerçek avantajlardan biri şu: Thunderbit’in yapay zekâsı düzen değişikliklerine otomatik olarak uyum sağlar. Klasik CSS seçici tabanlı kazıyıcılar, site işaretlemesini değiştirdiğinde bozulur — HN’nin HTML’i oldukça istikrarlı olsa da değişti (örneğin class="athing submission" güncellendi, eski a.storylink yerine span.titleline geldi). Yapay zekâ destekli bir kazıyıcı sayfayı her seferinde yeniden okur; bu yüzden sınıf adı değişiklikleriyle ilgilenmez.

python-vs-thunderbit-comparison.webp

Thunderbit ayrıca sayfalama işlemini de yönetir (HN’nin "More" düğmesine otomatik tıklama) ve alt sayfa kazımayı da yapar (tartışma verisini almak için her hikâyenin yorum sayfasını ziyaret etme). Yorum zenginleştirme kullanım senaryosunda, bu Yöntem 2’deki özyinelemeli API kodunun karşılığıdır — ama tek satır yazmadan.

Tercih konusu net: Özel mantığa, karmaşık veri dönüşümlerine, zamanlanmış otomasyon akışlarına ihtiyacınız varsa veya kod öğreniyorsanız Python doğru seçimdir. Veriyi hızlı almak, kod bakımına uğraşmamak ya da geliştirici olmamak istiyorsanız Thunderbit doğru seçimdir. Durumunuza uyan aracı seçin.

Python vs. API vs. Kodsuz: Hangi Yöntemi Seçmelisiniz?

İşte tam karar çerçevesi:

KriterBeautifulSoup (HTML)Firebase APIAlgolia APIThunderbit (Kodsuz)
Gerekli teknik beceriOrta seviye PythonBaşlangıç seviyesi PythonBaşlangıç seviyesi PythonYok
Kurulum süresi10–15 dk5–10 dk5–10 dk2 dk
Bakım yüküOrta (seçiciler bozulabilir)Düşük (stabil JSON)Düşük (stabil JSON)Yok
Veri derinliğiSadece ana sayfaHer öğe, kullanıcılarArama + geçmişAna sayfa + alt sayfalar
YorumlarZorKolay (özyinelemeli)Kolay (iç içe ağaç)Alt sayfa kazıma
Geçmiş veriHayırHayırEvet (tam arşiv)Hayır
Dışa aktarma seçenekleriKendiniz kodlarsınızKendiniz kodlarsınızKendiniz kodlarsınızYerleşik (Excel, Sheets vb.)
Zamanlamacron / GitHub Actionscron / GitHub Actionscron / GitHub ActionsYerleşik zamanlayıcı
En uygun kullanımKazımayı öğrenmeGüvenilir akışlarAraştırma ve analizHızlı veri çekimi

Python öğreniyorsanız veya özel bir şey geliştiriyorsanız Yöntem 1 ya da 2’yi seçin. Geçmiş analiz gerekiyorsa Algolia API’yi ekleyin. Sadece kod olmadan veri istiyorsanız Thunderbit’i deneyin.

Hacker News Kazıma İçin Thunderbit’i Deneyin

Sonuç ve Temel Çıkarımlar

Artık araç setinizde şunlar var:

  • Hacker News kazımak için iki eksiksiz Python yöntemi — HTML ayrıştırma için BeautifulSoup ve temiz JSON veri için Firebase API
  • Sayfa 1’in ötesine geçmek için sayfalama teknikleri — 2007’ye kadar uzanan geçmiş veriler için Algolia API dahil
  • CSV, Excel ve Google Sheets için dışa aktarma kodu — çünkü terminalde duran veri, ekip arkadaşlarınız için pek bir anlam ifade etmez
  • Üretim kalıpları — yeniden deneme mantığı, önbellekleme, tarama/ayrıştırma ayrımı ve cron ya da GitHub Actions ile zamanlanmış otomasyon
  • Python gerekmeyen durumlar için kodsuz bir alternatif

Benim tavsiyem: çoğu kullanım senaryosu için Firebase API (Yöntem 2) ile başlayın. Daha temiz, daha güvenilir ve iç içe HTML ayrıştırma zahmetine girmeden yorum erişimi sağlar. Geçmiş veriye ihtiyacınız olduğunda Algolia API’yi ekleyin. Ve sadece hızlı bir tabloya ihtiyaç duyduğunuz, tüm bir Python projesi açmak istemediğiniz anlar için Thunderbit’i yer imlerinizde tutun.

Daha derine inmek isterseniz HN yorumlarını duygu analizi için kazıyın, GitHub Actions ile günlük özet akışı kurun veya son on yılda teknoloji trendlerinin nasıl değiştiğini izlemek için Algolia API’yi keşfedin.

Hızlı Hacker News Kazıma İçin Thunderbit’i Deneyin Get Started Free

SSS

Hacker News’i kazımak yasal mı?

HN’nin verileri herkese açıktır ve Y Combinator programatik erişim için özel olarak resmî bir API sunar. Sitenin robots.txt dosyası salt okunur içeriğin kazınmasına (ana sayfa, öğe sayfaları, kullanıcı sayfaları) izin verir; ancak 30 saniyelik crawl gecikmesi ister. Bu gecikmeye uyun, etkileşimli uç noktaları (oy verme, giriş) kazımayın; böylece sağlam bir zemindesiniz. Kazıma etiği hakkında daha fazlası için web kazımanın yasal etkileri rehberimize bakın.

Hacker News’in resmî bir API’si var mı?

Evet. hacker-news.firebaseio.com/v0/ adresindeki HN Firebase API ücretsizdir, kimlik doğrulama gerektirmez ve hikâyelere, yorumlara, kullanıcı profillerine ve tüm akış türlerine (top, new, best, ask, show, jobs) erişim sağlar. Temiz JSON döndürür ve belirtilmiş bir rate limit yoktur; yine de istek sıklığında nazik davranmak her zaman önerilir.

Hacker News yorumlarını Python ile nasıl kazırım?

Firebase API kullanarak bir hikâye öğesini çekin ve onun kids alanını alın (üst seviye yorum ID’leri dizisi). Her yorum da kendi yanıt çocukları için kids alanına sahip bir öğedir. Her yorumu ve alt öğelerini çeken bir fonksiyonla ağacı özyinelemeli olarak gezin. Tam kod için yukarıdaki "Yorumları Kazıyın (Özyinelemeli Ağaç Gezimi)" bölümüne bakın. Alternatif olarak Algolia API’nin /items/<id> uç noktası, tüm iç içe yorum ağacını tek istekte döndürür — yorum yoğun hikâyeler için çok daha hızlıdır.

Hacker News’i kod yazmadan kazıyabilir miyim?

Evet. Thunderbit’in AI web scraper’ı bir Chrome eklentisi olarak çalışır — HN’yi açın, "AI Suggest Fields" seçeneğine tıklayın; başlık, URL, puan ve yazar gibi sütunları otomatik olarak belirler. "Scrape"e tıklayın ve doğrudan Excel, Google Sheets, Airtable veya Notion’a aktarın. Sayfalama desteği vardır ve yorum verisini çekmek için alt sayfaları bile ziyaret edebilir. Python yok, seçici yok, bakım yok.

Geçmiş Hacker News verisini nasıl alırım?

HN Algolia Search API bunun için en iyi araçtır. Tarih aralığına göre filtrelemek için numericFilters=created_at_i>TIMESTAMP ile search_by_date uç noktasını kullanın. Anahtar kelimeye göre arama yapabilir, hikâye türüne göre filtreleyebilir ve 500 sayfaya kadar sonuçta gezinebilirsiniz. Toplu geçmiş analiz için kamuya açık veri kümeleri ayrıca Google BigQuery (tam arşiv), ClickHouse (28 milyon kayıt) ve Hugging Face (4 milyon hikâye) üzerinde de bulunabilir.

Daha Fazla Bilgi

Shuai Guan
Shuai Guan
Thunderbit CEO’su | AI Veri Otomasyonu Uzmanı Shuai Guan, Thunderbit’in CEO’su ve University of Michigan Mühendislik mezunudur. Teknoloji ve SaaS mimarisi alanındaki yaklaşık on yıllık deneyiminden güç alarak, karmaşık yapay zeka modellerini pratik, kod yazmadan kullanılabilen veri çıkarma araçlarına dönüştürme konusunda uzmanlaşmıştır. Bu blogda, daha akıllı ve veriye dayalı iş akışları kurmanıza yardımcı olmak için web kazıma ve otomasyon stratejileri üzerine filtresiz, sahada sınanmış içgörüler paylaşıyor. Veri iş akışlarını optimize etmediği zamanlarda ise aynı detay odaklı yaklaşımını fotoğrafçılık tutkusuna da yansıtıyor.
İçindekiler
Thunderbit · AI web veri ajanı

Herhangi bir sayfadan 1 tık içinde veri çıkar

250.000+ kullanıcı tarafından güveniliyor
ücretsiz plan mevcut
Web sayfasından tabloya
İhtiyacını anlat — Thunderbit’in AI Ajanı bunu çeker ve Excel, Google Sheets, Airtable veya Notion’a aktarır. Başlamak ücretsiz.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week