batch batch

This commit is contained in:
salvacybersec
2025-11-13 04:12:05 +03:00
parent bb416e1f37
commit 2dc0eb8b19
6 changed files with 104 additions and 44 deletions

View File

@@ -60,9 +60,9 @@ curl -H "X-API-Key: demo_key_12345" \
# Channel Handle ile (API key query parametresi) # Channel Handle ile (API key query parametresi)
curl "http://localhost:5000/?channel=@tavakfi&format=Atom&api_key=demo_key_12345" curl "http://localhost:5000/?channel=@tavakfi&format=Atom&api_key=demo_key_12345"
# Channel URL ile # Channel URL ile (max_items: her istekte işlenecek transcript sayısı, default: 10, max: 100, 20'şer batch'ler)
curl -H "X-API-Key: demo_key_12345" \ curl -H "X-API-Key: demo_key_12345" \
"http://localhost:5000/?channel_url=https://www.youtube.com/@tavakfi&format=Atom&max_items=100" "http://localhost:5000/?channel_url=https://www.youtube.com/@tavakfi&format=Atom&max_items=50"
``` ```
**Detaylı API dokümantasyonu için:** [API.md](API.md) **Detaylı API dokümantasyonu için:** [API.md](API.md)
@@ -108,7 +108,7 @@ channel:
rss_bridge: rss_bridge:
base_url: "https://rss-bridge.org/bridge01" base_url: "https://rss-bridge.org/bridge01"
format: "Atom" format: "Atom"
max_items: 100 max_items: 100 # RSS-Bridge'den çekilecek video sayısı (web server'da max_items parametresi farklı)
``` ```
### Güvenlik Yapılandırması ### Güvenlik Yapılandırması
@@ -139,6 +139,29 @@ Sistem, işlenmiş transcript'leri **3 gün boyunca cache'de tutar**. Bu özelli
Cache kontrolü otomatik yapılır ve kullanıcı müdahalesi gerektirmez. Cache kontrolü otomatik yapılır ve kullanıcı müdahalesi gerektirmez.
### max_items Parametresi
Her API isteğinde kaç video transcript'inin işleneceğini kontrol eder:
- **Varsayılan**: 10 transcript
- **Maksimum**: 100 transcript
- **Kullanım**: `?max_items=50` query parametresi ile belirtilir
- **Batch İşleme**: 20'şer batch'ler halinde işlenir (YouTube IP blocking önleme için)
**Önemli Notlar:**
- `max_items` parametresi **her istekte işlenecek transcript sayısını** belirler
- RSS-Bridge'den daha fazla video çekilir (max_items × 2, minimum 50) çünkü bazı videolar transcript'siz olabilir
- **Batch İşleme**: YouTube IP blocking'i önlemek için 20'şer batch'ler halinde işlenir
- **Veritabanı Kaydı**: Her batch işlendikten sonra hemen veritabanına kaydedilir, böylece sonraki sorgularda görülebilir
- İlk isteklerde daha az transcript görebilirsiniz; sonraki isteklerde cache'den daha fazla transcript döner
**Örnek:**
```bash
# 50 transcript işle (20+20+10 batch'ler halinde)
curl -H "X-API-Key: demo_key_12345" \
"http://localhost:5000/?channel_id=UC9h8BDcXwkhZtnqoQJ7PggA&max_items=50&format=Atom"
```
## Proje Yapısı ## Proje Yapısı
``` ```

View File

@@ -29,7 +29,7 @@ security:
channel_id: 50 channel_id: 50
channel_handle: 50 channel_handle: 50
channel_url: 200 channel_url: 200
max_items: 500 max_items: 100 # Maksimum transcript sayısı (20'şer batch'ler halinde işlenir)
# CORS Settings # CORS Settings
cors: cors:

View File

@@ -325,12 +325,19 @@ channel_id = get_channel_id_from_handle(handle_url)
- **Cache Süresi**: `processed_at_utc` tarihine göre 3 gün kontrolü - **Cache Süresi**: `processed_at_utc` tarihine göre 3 gün kontrolü
- **Otomatik Yenileme**: 3 gün sonra cache geçersiz olur, yeni transcript çekilir - **Otomatik Yenileme**: 3 gün sonra cache geçersiz olur, yeni transcript çekilir
- [ ] Yeni video tespiti algoritması: - [ ] Yeni video tespiti algoritması:
1. RSS-Bridge feed'den son videoları çek 1. RSS-Bridge feed'den son videoları çek (max_items × 2, minimum 50 video)
2. SQLite veritabanında `video_id` ile sorgula 2. SQLite veritabanında `video_id` ile sorgula
3. Sadece yeni videoları (veritabanında olmayan) işle 3. Sadece yeni videoları (veritabanında olmayan) işle
4. **Cache Kontrolü**: İşlenmiş videolar için 3 günlük cache kontrolü yap 4. **Cache Kontrolü**: İşlenmiş videolar için 3 günlük cache kontrolü yap
- Eğer 3 gün içinde işlenmişse, transcript çıkarma (cache'den kullan) - Eğer 3 gün içinde işlenmişse, transcript çıkarma (cache'den kullan)
- 3 günden eskiyse, yeni transcript çek - 3 günden eskiyse, yeni transcript çek
5. **max_items Parametresi**: Her API isteğinde işlenecek transcript sayısı
- **Varsayılan**: 10 transcript
- **Maksimum**: 100 transcript
- **Kullanım**: `?max_items=50` query parametresi ile belirtilir
- **Batch İşleme**: 20'şer batch'ler halinde işlenir (YouTube IP blocking önleme için)
- **Veritabanı Kaydı**: Her batch işlendikten sonra hemen veritabanına kaydedilir
- **RSS-Bridge Limit**: max_items × 2 kadar video çekilir (bazı videolar transcript'siz olabilir)
- [ ] Transaction yönetimi (ACID compliance) - [ ] Transaction yönetimi (ACID compliance)
- [ ] Connection pooling ve error handling - [ ] Connection pooling ve error handling

View File

@@ -13,6 +13,11 @@ services:
environment: environment:
- PYTHONUNBUFFERED=1 - PYTHONUNBUFFERED=1
- FLASK_ENV=production - FLASK_ENV=production
dns:
- 100.64.0.39 # Host DNS server
- 8.8.8.8 # Google DNS (fallback)
- 1.1.1.1 # Cloudflare DNS (fallback)
network_mode: bridge
restart: unless-stopped restart: unless-stopped
# Web server modu (varsayılan) # Web server modu (varsayılan)
command: python app.py command: python app.py

View File

@@ -177,12 +177,13 @@ class SecurityManager:
max_items parametresini doğrula max_items parametresini doğrula
Args: Args:
max_items: Maksimum item sayısı max_items: Maksimum transcript sayısı (her istekte işlenecek)
Returns: Returns:
Geçerli mi? Geçerli mi?
""" """
return isinstance(max_items, int) and 1 <= max_items <= 500 # Maksimum 100 transcript (20'şer batch'ler halinde işlenir)
return isinstance(max_items, int) and 1 <= max_items <= 100
# Global security manager instance # Global security manager instance
@@ -312,7 +313,7 @@ def validate_input(f):
if not security.validate_max_items(max_items_int): if not security.validate_max_items(max_items_int):
return jsonify({ return jsonify({
'error': 'Geçersiz max_items değeri', 'error': 'Geçersiz max_items değeri',
'message': 'max_items 1-500 arasında olmalı' 'message': 'max_items 1-100 arasında olmalı (20\'şer batch\'ler halinde işlenir)'
}), 400 }), 400
except ValueError: except ValueError:
return jsonify({ return jsonify({

View File

@@ -6,6 +6,7 @@ from typing import Optional
import sys import sys
import os import os
import yaml import yaml
import time
from pathlib import Path from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent)) sys.path.insert(0, str(Path(__file__).parent.parent))
@@ -176,13 +177,15 @@ def process_channel(channel_id: str, max_items: int = 50) -> dict:
extractor = get_extractor() extractor = get_extractor()
cleaner = get_cleaner() cleaner = get_cleaner()
# RSS-Bridge'den videoları çek # RSS-Bridge'den videoları çek (max_items'ın 2 katı kadar çek, böylece yeterli video olur)
# RSS-Bridge'den daha fazla video çekiyoruz çünkü bazıları transcript'siz olabilir
rss_bridge_limit = max(max_items * 2, 50) # En az 50 video çek
try: try:
videos = fetch_videos_from_rss_bridge( videos = fetch_videos_from_rss_bridge(
base_url="https://rss-bridge.org/bridge01", base_url="https://rss-bridge.org/bridge01",
channel_id=channel_id, channel_id=channel_id,
format="Atom", format="Atom",
max_items=max_items max_items=rss_bridge_limit
) )
except Exception as e: except Exception as e:
raise Exception(f"RSS-Bridge hatası: {e}") raise Exception(f"RSS-Bridge hatası: {e}")
@@ -193,12 +196,25 @@ def process_channel(channel_id: str, max_items: int = 50) -> dict:
if not db.is_video_processed(video['video_id']): if not db.is_video_processed(video['video_id']):
db.add_video(video) db.add_video(video)
# Bekleyen videoları işle (YouTube IP blocking'i önlemek için sadece 5 video) # Bekleyen videoları işle (max_items kadar, 20'şer batch'ler halinde)
pending_videos = db.get_pending_videos()[:5] # YouTube IP blocking'i önlemek için her batch'te 20 video işlenir
# max_items: Her istekte kaç video transcript işleneceği (maksimum 100)
batch_size = 20 # Her batch'te işlenecek video sayısı
processed_count = 0 # İşlenen transcript sayısı
for video in pending_videos: # Tüm bekleyen videoları al (channel_id'ye göre filtrele)
if video['channel_id'] != channel_id: all_pending_videos = [v for v in db.get_pending_videos() if v['channel_id'] == channel_id]
continue
# max_items kadar transcript işlenene kadar batch'ler halinde işle
for batch_start in range(0, len(all_pending_videos), batch_size):
if processed_count >= max_items:
break
batch_videos = all_pending_videos[batch_start:batch_start + batch_size]
for video in batch_videos:
if processed_count >= max_items:
break
# Cache kontrolü: 3 gün içinde işlenmiş transcript varsa atla # Cache kontrolü: 3 gün içinde işlenmiş transcript varsa atla
if db.is_transcript_cached(video['video_id'], cache_days=3): if db.is_transcript_cached(video['video_id'], cache_days=3):
@@ -216,7 +232,7 @@ def process_channel(channel_id: str, max_items: int = 50) -> dict:
# Transcript temizle # Transcript temizle
raw, clean = cleaner.clean_transcript(transcript, sentences_per_paragraph=3) raw, clean = cleaner.clean_transcript(transcript, sentences_per_paragraph=3)
# Veritabanına kaydet # Veritabanına kaydet (her batch hemen kaydedilir)
db.update_video_transcript( db.update_video_transcript(
video['video_id'], video['video_id'],
raw, raw,
@@ -224,10 +240,16 @@ def process_channel(channel_id: str, max_items: int = 50) -> dict:
status=1, status=1,
language='tr' language='tr'
) )
processed_count += 1
print(f"Video {video['video_id']} transcript'i işlendi ve veritabanına kaydedildi ({processed_count}/{max_items})")
except Exception as e: except Exception as e:
print(f"Transcript çıkarım hatası {video['video_id']}: {e}") print(f"Transcript çıkarım hatası {video['video_id']}: {e}")
db.mark_video_failed(video['video_id'], str(e)) db.mark_video_failed(video['video_id'], str(e))
# Batch tamamlandı, kısa bir bekleme (rate limiting için)
if processed_count < max_items and batch_start + batch_size < len(all_pending_videos):
time.sleep(2) # Batch'ler arası 2 saniye bekleme
# İşlenmiş videoları getir # İşlenmiş videoları getir
processed_videos = db.get_processed_videos( processed_videos = db.get_processed_videos(
limit=max_items, limit=max_items,
@@ -259,9 +281,11 @@ def generate_feed():
channel_url = request.args.get('channel_url') channel_url = request.args.get('channel_url')
format_type = request.args.get('format', 'Atom').lower() # Atom veya Rss format_type = request.args.get('format', 'Atom').lower() # Atom veya Rss
try: try:
max_items = int(request.args.get('max_items', 50)) max_items = int(request.args.get('max_items', 10)) # Default: 10 transcript
# Maksimum 100 transcript (20'şer batch'ler halinde işlenir)
max_items = min(max_items, 100)
except (ValueError, TypeError): except (ValueError, TypeError):
max_items = 50 max_items = 10
# Channel ID'yi normalize et # Channel ID'yi normalize et
normalized_channel_id = normalize_channel_id( normalized_channel_id = normalize_channel_id(
@@ -278,7 +302,7 @@ def generate_feed():
'channel': '@username veya username', 'channel': '@username veya username',
'channel_url': 'https://www.youtube.com/@username veya https://www.youtube.com/channel/UC...', 'channel_url': 'https://www.youtube.com/@username veya https://www.youtube.com/channel/UC...',
'format': 'Atom veya Rss (varsayılan: Atom)', 'format': 'Atom veya Rss (varsayılan: Atom)',
'max_items': 'Maksimum video sayısı (varsayılan: 50)' 'max_items': 'Maksimum transcript sayısı (varsayılan: 10, maksimum: 100, 20\'şer batch\'ler halinde işlenir)'
} }
}), 400 }), 400
@@ -362,12 +386,12 @@ def info():
'channel': '@username veya username', 'channel': '@username veya username',
'channel_url': 'Full YouTube channel URL', 'channel_url': 'Full YouTube channel URL',
'format': 'Atom veya Rss (varsayılan: Atom)', 'format': 'Atom veya Rss (varsayılan: Atom)',
'max_items': 'Maksimum video sayısı (varsayılan: 50)' 'max_items': 'Her istekte işlenecek maksimum transcript sayısı (varsayılan: 10, maksimum: 100, 20\'şer batch\'ler halinde işlenir)'
}, },
'examples': [ 'examples': [
'/?channel_id=UC9h8BDcXwkhZtnqoQJ7PggA&format=Atom', '/?channel_id=UC9h8BDcXwkhZtnqoQJ7PggA&format=Atom',
'/?channel=@tavakfi&format=Rss', '/?channel=@tavakfi&format=Rss',
'/?channel_url=https://www.youtube.com/@tavakfi&format=Atom&max_items=100' '/?channel_url=https://www.youtube.com/@tavakfi&format=Atom&max_items=50'
] ]
}) })