?
This commit is contained in:
@@ -220,13 +220,46 @@ class TranscriptExtractor:
|
||||
else:
|
||||
logger.warning(f"[FLARESOLVERR] ⚠️ Transcript URL'leri bulunamadı HTML'de")
|
||||
else:
|
||||
# POST istekleri için JSON kontrolü
|
||||
try:
|
||||
# POST istekleri için JSON kontrolü ve HTML içindeki JSON extract
|
||||
import re
|
||||
import json
|
||||
|
||||
# HTML içinde JSON var mı kontrol et (<pre> tag'i içinde olabilir)
|
||||
if response_content.strip().startswith('<html') or response_content.strip().startswith('<'):
|
||||
# HTML içinde JSON ara
|
||||
json_match = re.search(r'<pre[^>]*>(.*?)</pre>', response_content, re.DOTALL)
|
||||
if json_match:
|
||||
json_content = json_match.group(1).strip()
|
||||
try:
|
||||
parsed_json = json.loads(json_content)
|
||||
logger.debug(f"[FLARESOLVERR] ✅ POST response HTML içinde JSON bulundu ve parse edildi")
|
||||
|
||||
# Hata kontrolü
|
||||
if 'error' in parsed_json:
|
||||
error_code = parsed_json.get('error', {}).get('code', 'unknown')
|
||||
error_message = parsed_json.get('error', {}).get('message', 'unknown')
|
||||
error_status = parsed_json.get('error', {}).get('status', '')
|
||||
logger.warning(f"[FLARESOLVERR] ⚠️ POST response'unda hata: {error_code} - {error_message}")
|
||||
|
||||
# FAILED_PRECONDITION hatası varsa, FlareSolverr POST istekleri için uygun değil
|
||||
if error_code == 400 and 'FAILED_PRECONDITION' in error_status:
|
||||
logger.warning(f"[FLARESOLVERR] ⚠️ YouTube API FlareSolverr POST isteklerini reddediyor (FAILED_PRECONDITION)")
|
||||
logger.warning(f"[FLARESOLVERR] POST istekleri için FlareSolverr kullanılmayacak")
|
||||
|
||||
# HTML yerine JSON kullan (response_content'i güncelle)
|
||||
response_content = json_content
|
||||
logger.debug(f"[FLARESOLVERR] ✅ POST response HTML'den JSON extract edildi")
|
||||
except json.JSONDecodeError:
|
||||
logger.warning(f"[FLARESOLVERR] ⚠️ POST response HTML içindeki JSON parse edilemedi")
|
||||
else:
|
||||
logger.warning(f"[FLARESOLVERR] ⚠️ POST response HTML ama içinde JSON bulunamadı")
|
||||
else:
|
||||
# Direkt JSON kontrolü
|
||||
try:
|
||||
json.loads(response_content)
|
||||
logger.debug(f"[FLARESOLVERR] ✅ POST response geçerli JSON")
|
||||
except:
|
||||
logger.warning(f"[FLARESOLVERR] ⚠️ POST response JSON değil, HTML olabilir")
|
||||
logger.warning(f"[FLARESOLVERR] ⚠️ POST response JSON değil")
|
||||
|
||||
# Response objesine transcript URL'lerini ve analiz sonuçlarını ekle (alternatif parse için)
|
||||
response_obj = FlareSolverrResponse(status_code, response_content, headers, url, is_post=is_post_request)
|
||||
@@ -369,58 +402,13 @@ class TranscriptExtractor:
|
||||
return original_get(session_self, url, **kwargs)
|
||||
|
||||
def patched_post(session_self, url, **kwargs):
|
||||
"""requests.Session.post'i patch et - header'ları ekle ve FlareSolverr kullan"""
|
||||
# YouTube API endpoint'leri için FlareSolverr kullan (youtubei/v1/player gibi)
|
||||
"""requests.Session.post'i patch et - header'ları ekle (FlareSolverr POST için kullanılmıyor)"""
|
||||
# NOT: YouTube API POST istekleri FlareSolverr ile çalışmıyor (FAILED_PRECONDITION hatası)
|
||||
# Bu yüzden POST istekleri için FlareSolverr kullanmayalım, sadece header'ları ekle
|
||||
is_youtube_api = ('youtube.com' in url or 'youtu.be' in url) and ('/youtubei/v1/' in url or '/api/' in url)
|
||||
|
||||
# FlareSolverr kullanılıyorsa ve YouTube API endpoint'i ise
|
||||
if extractor_instance.use_flaresolverr and is_youtube_api and extractor_instance.flaresolverr_available:
|
||||
logger.debug(f"[FLARESOLVERR] YouTube API POST isteği FlareSolverr üzerinden deneniyor: {url[:50]}...")
|
||||
# POST için FlareSolverr'da request.post kullan
|
||||
flaresolverr_response = extractor_instance._make_flaresolverr_request(url, 'POST', **kwargs)
|
||||
if flaresolverr_response:
|
||||
logger.debug(f"[FLARESOLVERR] ✅ FlareSolverr POST başarılı, response döndürülüyor")
|
||||
class PatchedResponse:
|
||||
def __init__(self, flaresolverr_response):
|
||||
self.status_code = flaresolverr_response.status_code
|
||||
self.text = flaresolverr_response.text
|
||||
self.content = flaresolverr_response.content
|
||||
self.headers = flaresolverr_response.headers
|
||||
self.url = flaresolverr_response.url
|
||||
self.ok = 200 <= self.status_code < 300
|
||||
|
||||
def json(self):
|
||||
import json
|
||||
try:
|
||||
# Debug: JSON parse edilmeye çalışılan içeriği logla
|
||||
logger.debug(f"[FLARESOLVERR] JSON parse deneniyor (POST), içerik tipi: {type(self.text)}, uzunluk: {len(self.text)}")
|
||||
logger.debug(f"[FLARESOLVERR] İçerik önizleme (ilk 200 karakter): {self.text[:200]}")
|
||||
|
||||
# Eğer HTML ise JSON parse etme
|
||||
if self.text.strip().startswith('<') or 'html' in self.headers.get('content-type', '').lower():
|
||||
logger.warning(f"[FLARESOLVERR] ⚠️ HTML içerik JSON olarak parse edilmeye çalışılıyor, boş dict döndürülüyor")
|
||||
return {}
|
||||
|
||||
return json.loads(self.text)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.error(f"[FLARESOLVERR] ❌ JSON parse hatası (POST): {e}")
|
||||
logger.error(f"[FLARESOLVERR] İçerik (ilk 500 karakter): {self.text[:500]}")
|
||||
return {}
|
||||
except Exception as e:
|
||||
logger.error(f"[FLARESOLVERR] ❌ JSON parse beklenmeyen hata (POST): {type(e).__name__} - {str(e)}")
|
||||
return {}
|
||||
|
||||
def raise_for_status(self):
|
||||
"""requests.Response.raise_for_status() uyumluluğu"""
|
||||
if not self.ok:
|
||||
from requests.exceptions import HTTPError
|
||||
raise HTTPError(f"{self.status_code} Client Error: {self.text[:100]}", response=self)
|
||||
|
||||
return PatchedResponse(flaresolverr_response)
|
||||
else:
|
||||
logger.debug(f"[FLARESOLVERR] FlareSolverr POST yanıt vermedi, normal istek deneniyor")
|
||||
elif extractor_instance.use_flaresolverr and ('youtube.com' in url or 'youtu.be' in url):
|
||||
logger.debug(f"[FLARESOLVERR] POST isteği tespit edildi, FlareSolverr kullanılmıyor (sadece header'lar): {url[:50]}...")
|
||||
if is_youtube_api:
|
||||
logger.debug(f"[FLARESOLVERR] POST isteği tespit edildi, FlareSolverr kullanılmıyor (FAILED_PRECONDITION önleme): {url[:50]}...")
|
||||
|
||||
# Normal istek (header'ları ekle)
|
||||
headers = kwargs.get('headers', {})
|
||||
@@ -638,16 +626,57 @@ class TranscriptExtractor:
|
||||
logger.error(f"[TRANSCRIPT] Hata detayları: {error_msg[:500]}")
|
||||
logger.error(f"[TRANSCRIPT] Bu video için transcript çıkarılamıyor (YouTube HTML yapısı değişmiş olabilir)")
|
||||
|
||||
# Debug: FlareSolverr response'unu analiz et (eğer kullanıldıysa)
|
||||
# Debug: FlareSolverr response'unu analiz et ve transcript URL'lerini kullan (fallback)
|
||||
if self.use_flaresolverr and hasattr(self, '_last_flaresolverr_response'):
|
||||
logger.debug(f"[TRANSCRIPT] FlareSolverr response analizi yapılıyor...")
|
||||
last_response = self._last_flaresolverr_response
|
||||
|
||||
# Transcript URL'leri var mı kontrol et
|
||||
# Transcript URL'leri var mı kontrol et ve kullan (fallback)
|
||||
transcript_urls = getattr(last_response, 'transcript_urls', [])
|
||||
if transcript_urls:
|
||||
logger.warning(f"[TRANSCRIPT] ⚠️ FlareSolverr response'unda {len(transcript_urls)} transcript URL bulundu ama parse edilemedi")
|
||||
logger.warning(f"[TRANSCRIPT] Bu URL'ler doğrudan kullanılabilir (fallback mekanizması henüz implement edilmedi)")
|
||||
logger.warning(f"[TRANSCRIPT] ⚠️ FlareSolverr response'unda {len(transcript_urls)} transcript URL bulundu, fallback mekanizması deneniyor...")
|
||||
|
||||
# İlk transcript URL'ini kullan (genellikle en uygun dil)
|
||||
transcript_url = transcript_urls[0]
|
||||
|
||||
# Unicode escape karakterlerini decode et (\u0026 -> &)
|
||||
import codecs
|
||||
transcript_url = codecs.decode(transcript_url, 'unicode_escape')
|
||||
|
||||
logger.info(f"[TRANSCRIPT] Transcript URL'den transcript çekiliyor: {transcript_url[:100]}...")
|
||||
|
||||
try:
|
||||
import requests
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
# Transcript URL'inden XML çek (browser header'ları ile)
|
||||
headers = TranscriptExtractor._get_browser_headers()
|
||||
response = requests.get(transcript_url, headers=headers, timeout=30)
|
||||
response.raise_for_status()
|
||||
|
||||
# XML'i parse et
|
||||
root = ET.fromstring(response.text)
|
||||
|
||||
# Transcript segment'lerini çıkar
|
||||
transcript_list = []
|
||||
for text_elem in root.findall('.//text'):
|
||||
start = float(text_elem.get('start', 0))
|
||||
duration = float(text_elem.get('dur', 0))
|
||||
text = text_elem.text or ''
|
||||
|
||||
transcript_list.append({
|
||||
'text': text,
|
||||
'start': start,
|
||||
'duration': duration
|
||||
})
|
||||
|
||||
if transcript_list:
|
||||
logger.info(f"[TRANSCRIPT] ✅ Transcript URL'den {len(transcript_list)} segment başarıyla çıkarıldı (fallback)")
|
||||
return transcript_list
|
||||
else:
|
||||
logger.warning(f"[TRANSCRIPT] ⚠️ Transcript URL'den segment bulunamadı")
|
||||
except Exception as fallback_err:
|
||||
logger.error(f"[TRANSCRIPT] ❌ Transcript URL fallback hatası: {type(fallback_err).__name__} - {str(fallback_err)[:200]}")
|
||||
|
||||
# ytInitialPlayerResponse var mı kontrol et
|
||||
yt_response_found = getattr(last_response, 'yt_initial_player_response_found', False)
|
||||
|
||||
Reference in New Issue
Block a user