diff --git a/src/transcript_extractor.py b/src/transcript_extractor.py index c000667..d0a9d9d 100644 --- a/src/transcript_extractor.py +++ b/src/transcript_extractor.py @@ -554,6 +554,112 @@ class TranscriptExtractor: error_msg = str(e) error_type = type(e).__name__ + # JSONDecodeError: POST response JSON parse edilemiyor (HTML veya başka format olabilir) + if "JSONDecodeError" in error_type or "json" in error_msg.lower(): + logger.error(f"[TRANSCRIPT] ❌ Video {video_id} JSON parse hatası: {error_type} - {error_msg[:300]}") + logger.debug(f"[TRANSCRIPT] Hata detayları: error_type={error_type}, error_msg={error_msg[:500]}") + + # FlareSolverr response'unda transcript URL'leri varsa kullan (fallback) + transcript_urls = [] + last_response = None + + # Debug: _last_flaresolverr_response'un varlığını kontrol et + if self.use_flaresolverr: + logger.debug(f"[TRANSCRIPT] FlareSolverr durumu: use_flaresolverr={self.use_flaresolverr}, hasattr={hasattr(self, '_last_flaresolverr_response')}") + + if hasattr(self, '_last_flaresolverr_response'): + last_response = self._last_flaresolverr_response + logger.debug(f"[TRANSCRIPT] _last_flaresolverr_response bulundu: {type(last_response).__name__}") + + # transcript_urls'i al + transcript_urls = getattr(last_response, 'transcript_urls', []) + logger.debug(f"[TRANSCRIPT] transcript_urls sayısı: {len(transcript_urls)}") + + # Eğer transcript_urls boşsa, FlareSolverr GET response'unu yeniden parse et + if not transcript_urls and hasattr(last_response, 'text'): + logger.warning(f"[TRANSCRIPT] ⚠️ transcript_urls boş, FlareSolverr GET response'unu yeniden parse ediliyor...") + import re + + # HTML'den transcript URL'lerini çıkar + response_content = last_response.text + transcript_urls = re.findall(r'https?://[^"\s<>]+timedtext[^"\s<>]*', response_content) + + if transcript_urls: + logger.info(f"[TRANSCRIPT] ✅ HTML'den {len(transcript_urls)} transcript URL bulundu (yeniden parse)") + logger.debug(f"[TRANSCRIPT] İlk transcript URL: {transcript_urls[0][:150]}...") + # transcript_urls'i last_response'a kaydet (gelecek kullanım için) + # Attribute yoksa oluştur, varsa güncelle + last_response.transcript_urls = transcript_urls + else: + logger.warning(f"[TRANSCRIPT] ⚠️ HTML'den transcript URL bulunamadı") + else: + logger.warning(f"[TRANSCRIPT] ⚠️ _last_flaresolverr_response bulunamadı, fallback kullanılamıyor") + + # Fallback mekanizması: transcript URL'lerini kullan + if transcript_urls: + logger.warning(f"[TRANSCRIPT] ⚠️ JSON parse hatası, transcript URL fallback deneniyor ({len(transcript_urls)} URL bulundu)...") + + # Tüm transcript URL'lerini dene (ilk başarılı olanı kullan) + for idx, transcript_url_raw in enumerate(transcript_urls): + try: + # Unicode escape karakterlerini decode et + import codecs + transcript_url = codecs.decode(transcript_url_raw, 'unicode_escape') + + # URL'in geçerli olup olmadığını kontrol et + if not transcript_url.startswith('http'): + logger.warning(f"[TRANSCRIPT] ⚠️ Geçersiz transcript URL (deneme {idx + 1}/{len(transcript_urls)}): {transcript_url[:100]}...") + continue + + logger.info(f"[TRANSCRIPT] Transcript URL'den transcript çekiliyor ({idx + 1}/{len(transcript_urls)}): {transcript_url[:100]}...") + + import requests + import xml.etree.ElementTree as ET + + # Transcript URL'inden XML çek + 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ı (JSONDecodeError fallback, URL {idx + 1}/{len(transcript_urls)})") + return transcript_list + else: + logger.warning(f"[TRANSCRIPT] ⚠️ Transcript URL'den segment bulunamadı (deneme {idx + 1}/{len(transcript_urls)})") + except Exception as fallback_err: + logger.error(f"[TRANSCRIPT] ❌ Transcript URL fallback hatası (deneme {idx + 1}/{len(transcript_urls)}): {type(fallback_err).__name__} - {str(fallback_err)[:200]}") + # Bir sonraki URL'i dene + continue + + # Tüm URL'ler başarısız oldu + logger.error(f"[TRANSCRIPT] ❌ Tüm transcript URL'leri başarısız oldu ({len(transcript_urls)} URL denendi)") + else: + logger.warning(f"[TRANSCRIPT] ⚠️ Transcript URL fallback kullanılamıyor (transcript_urls boş)") + + # Retry yap (fallback başarısız olduysa) + if attempt < max_retries: + logger.warning(f"[TRANSCRIPT] ⚠️ Retry yapılacak (Deneme {attempt + 1}/{max_retries})...") + continue + else: + logger.error(f"[TRANSCRIPT] ❌ Video {video_id} JSON parse hatası - Tüm denemeler başarısız (fallback ve retry)") + return None + # AttributeError: 'NoneType' object has no attribute 'get' hatası # Bu genellikle FlareSolverr'dan dönen HTML'in parse edilememesinden kaynaklanır if "AttributeError" in error_type and "'NoneType' object has no attribute 'get'" in error_msg: