HEGS Scrapper, Anadolu Ajansı ve diğer haber kaynaklarından haber içeriklerini çekmek için tasarlanmış web scraping API'sidir. BeautifulSoup ve akıllı container seçimi ile haber metinlerini temiz ve yapılandırılmış şekilde çıkarır.
- Akıllı Content Extraction: Otomatik haber container tespiti
- Meta Data Parsing: Başlık, tarih, yazar bilgileri
- Error Handling: Retry mekanizması ve graceful degradation
- RSS Feed Support: Anadolu Ajansı RSS entegrasyonu
- Clean Text Output: Gereksiz HTML ve whitespace temizleme
- Multiple Selectors: 12+ farklı haber container selector
- Turkish Support: Türkçe özel karakter desteği
POST /scrape- URL'den haber içeriği çekmeGET /- API sağlık kontrolü
- Framework: FastAPI 0.104.1
- Parser: BeautifulSoup4 4.12.2
- HTTP Client: Requests 2.31.0
- HTML Parser: lxml 4.9.3
- Python: 3.8+
Bu servis HEGS mikroservis ekosisteminin bir parçasıdır ve HEGS-SETUP reposu üzerinden Docker Compose ile çalıştırılır.
Tüm HEGS sistemini kurmak ve çalıştırmak için:
- HEGS-SETUP reposuna gidin: HEGS-SETUP Repository
- HEGS-SETUP README'sindeki adımları takip edin
- Tüm mikroservisler otomatik olarak başlatılacaktır
Not: Bu servisi tek başına çalıştırmak için Docker Compose yerine manuel kurulum yapabilirsiniz, ancak tam fonksiyonellik için HEGS-SETUP kullanılması önerilir.
curl -X POST "http://localhost:9932/scrape" \
-H "Content-Type: application/json" \
-d '{
"url": "https://www.aa.com.tr/tr/guncel/istanbul-buyuksehir-belediyesi-2024-yili-butcesi-uygulamaya-konuldu/3070000"
}'Success Response:
{
"success": true,
"title": "İstanbul Büyükşehir Belediyesi 2024 yılı bütçesi uygulamaya konuldu",
"published": "2024-01-15T14:30:00",
"content": "İstanbul Büyükşehir Belediyesi'nin 2024 yılı bütçesi Meclis'te kabul edildi.\n\nBelediye Başkanı Ekrem İmamoğlu, bütçe görüşmelerinde yaptığı konuşmada...",
"error": null
}Error Response:
{
"success": false,
"title": null,
"published": null,
"content": null,
"error": "İçerik bulunamadı - uygun makale konteyneri bulunamadı"
}curl -X GET "http://localhost:9932/"Response:
{
"message": "RSS Content Scraper API is running"
}HEGS-SCRAPPER/
├── api.py # FastAPI uygulaması & scraping mantığı
├── main.py # RSS feed reader (Anadolu Ajansı)
├── aa_inspect.py # Test ve debug script
├── test_api.py # API test script
├── requirements.txt # Python bağımlılıkları
└── README.md # Bu dosya
Sistem şu sırayla container arar:
KNOWN_SELECTORS = [
"article",
"div[itemprop='articleBody']",
"section[itemprop='articleBody']",
"div[class*='article']",
"section[class*='article']",
"div[class*='content']",
"section[class*='content']",
"div[class*='detail']",
"section[class*='detail']",
"div[class*='haber']",
"section[class*='haber']",
"div[class*='icerik']",
"section[class*='icerik']",
]Her container şu kriterlere göre puanlanır:
def score_container(tag) -> int:
# Paragraph sayısı ve uzunluğu
text_length = len(all_text)
# Header sayısı (h2, h3) - pozitif
headers_score = 100 * len(headers)
# Link sayısı - negatif (navigation içeriği olabilir)
links_penalty = -10 * len(links)
# Minimum eşik: 300 karakter, 2+ paragraf
if text_length < 300 or paragraph_count < 2:
return 0
return text_length + headers_score + links_penalty# Sırasıyla dener:
1. <meta property="og:title">
2. <meta property="twitter:title">
3. <meta name="title">
4. <h1> tag
5. <title> tag# Sırasıyla dener:
1. <meta property="article:published_time">
2. <meta property="og:updated_time">
3. <meta name="pubdate">
4. <time datetime="...">
5. Regex pattern match (DD.MM.YYYY veya YYYY-MM-DD)def clean_text(s: str) -> str:
# Birden fazla whitespace'i tek space'e
s = re.sub(r"\s+", " ", s)
# Başındaki ve sonundaki boşlukları temizle
return s.strip()def fetch_rss_category(category: str):
"""
Kategoriler:
- guncel, dunya, ekonomi, spor, teknoloji
- saglik, kultur, egitim, cevre, yasam
"""
url = f"https://www.aa.com.tr/tr/rss/default?cat={category}"
# RSS parse ve haber listesi döndürpython main.py
# Output: RSS feed'den haberlerREQUEST_TIMEOUT = 12 # Saniye
RETRY = 2 # Retry count
SLEEP_BETWEEN_REQ = 1.0 # İstekler arası beklemeUA = "HegsHaberScraper/1.0" # Custom user agent- URL format kontrolü (Pydantic HttpUrl)
- Timeout mekanizması
- Exception handling
- CORS restrictions
allow_origins=[
"http://localhost:5173", # frontend
"http://localhost:3000" # frontend fallback
]ArticlePage.tsx
const response = await axios.post(
"http://localhost:9932/scrape",
{ url: articleUrl }
);NewsCard.tsx
// Quiz oluşturma için haber içeriği
const scrapingResponse = await axios.post(
"http://localhost:9932/scrape",
{ url: newsUrl }
);
// Sonra AI'a gönder
const quizResponse = await axios.post(
"http://localhost:8000/quiz",
{ news_text: scrapingResponse.data.content }
);// NewsService.java
String scrapperUrl = "http://localhost:9932/scrape";
RestTemplate restTemplate = new RestTemplate();
ScrapeRequest request = new ScrapeRequest(newsUrl);
ScrapeResponse response = restTemplate.postForObject(
scrapperUrl,
request,
ScrapeResponse.class
);- Ortalama Scraping Süresi: 2-4 saniye
- Retry ile: max 10 saniye
- Success Rate: ~85% (desteklenen siteler)
- Memory Usage: ~80MB (base)
- Concurrent Requests: 20+ (asyncio ile artırılabilir)
# API test
python test_api.py
# Çıktı: Scraping başarılı/başarısızimport logging
logging.basicConfig(level=logging.DEBUG)
# api.py içinde
logger = logging.getLogger(__name__)
logger.debug(f"Scraping URL: {url}")-
"Sayfa alınamadı" Hatası
Çözüm: - URL'i kontrol edin - Site erişilebilir mi kontrol edin - Timeout süresini artırın -
"İçerik bulunamadı" Hatası
Çözüm: - Site yapısı desteklenmiyor olabilir - KNOWN_SELECTORS listesine yeni selector ekleyin - Scoring algoritmasını ayarlayın -
Encoding Hataları
Çözüm: - lxml parser kullanılıyor - UTF-8 encoding zorunlu
# Python REPL
from api import scrape_article
result = scrape_article("https://www.aa.com.tr/tr/guncel/test-haber/123456")
print(result)# Başarılı case
curl -X POST http://localhost:9932/scrape \
-H "Content-Type: application/json" \
-d '{"url": "https://www.aa.com.tr/tr/guncel/valid-news-url"}'
# Geçersiz URL
curl -X POST http://localhost:9932/scrape \
-H "Content-Type: application/json" \
-d '{"url": "invalid-url"}'- ✅ Anadolu Ajansı (aa.com.tr)
- ✅ Genel haber siteleri (article tag'li)
- ✅ Schema.org microdata kullanan siteler
⚠️ Dinamik JavaScript içerikli siteler (gelecekte)⚠️ Login gerektiren siteler (gelecekte)
- ❌ SPA (Single Page Application) siteleri
- ❌ Captcha korumalı siteler
- ❌ Paywall arkasındaki içerikler
# api.py içinde
KNOWN_SELECTORS = [
# Mevcut selector'lar
"your-custom-selector",
"div[class*='your-class']"
]def score_container(tag) -> int:
# Minimum karakter sayısını değiştir
MIN_TEXT_LENGTH = 200 # varsayılan: 300
MIN_PARAGRAPHS = 1 # varsayılan: 2
# Ağırlıkları ayarla
HEADER_WEIGHT = 150 # varsayılan: 100
LINK_PENALTY = -5 # varsayılan: -10Not: Bu servis localhost üzerinde çalışacak şekilde yapılandırılmıştır. Docker ile çalıştırmak için root dizindeki docker-compose.yml dosyasını kullanın.