player error
This commit is contained in:
@@ -69,7 +69,8 @@ class TranscriptExtractor:
|
|||||||
try:
|
try:
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
test_response = requests.get(f"{self.flaresolverr_url.replace('/v1', '')}/v1", timeout=5)
|
# Timeout'u kısalt (erişilemezse hemen normal isteğe geç)
|
||||||
|
test_response = requests.get(f"{self.flaresolverr_url.replace('/v1', '')}/v1", timeout=3)
|
||||||
if test_response.status_code == 405: # Method Not Allowed normal (GET yerine POST bekliyor)
|
if test_response.status_code == 405: # Method Not Allowed normal (GET yerine POST bekliyor)
|
||||||
logger.info("[FLARESOLVERR] ✅ FlareSolverr erişilebilir")
|
logger.info("[FLARESOLVERR] ✅ FlareSolverr erişilebilir")
|
||||||
self.flaresolverr_available = True
|
self.flaresolverr_available = True
|
||||||
@@ -78,11 +79,15 @@ class TranscriptExtractor:
|
|||||||
logger.warning(f"[FLARESOLVERR] ⚠️ FlareSolverr yanıtı beklenmedik: {test_response.status_code}")
|
logger.warning(f"[FLARESOLVERR] ⚠️ FlareSolverr yanıtı beklenmedik: {test_response.status_code}")
|
||||||
self.flaresolverr_available = False
|
self.flaresolverr_available = False
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
except requests.exceptions.Timeout:
|
||||||
logger.warning(f"[FLARESOLVERR] ⚠️ FlareSolverr test edilemedi: {e}")
|
logger.warning(f"[FLARESOLVERR] ⚠️ FlareSolverr timeout (erişilemiyor), normal istekler kullanılacak")
|
||||||
logger.warning(f"[FLARESOLVERR] Test başarısız, ancak gerçek isteklerde tekrar denenilecek")
|
|
||||||
self.flaresolverr_available = False
|
self.flaresolverr_available = False
|
||||||
# use_flaresolverr'ı False yapma, gerçek isteklerde tekrar dene
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"[FLARESOLVERR] ⚠️ FlareSolverr test edilemedi: {type(e).__name__} - {str(e)[:100]}")
|
||||||
|
logger.warning(f"[FLARESOLVERR] Test başarısız, ancak gerçek isteklerde tekrar denenilecek (timeout: 10s)")
|
||||||
|
self.flaresolverr_available = False
|
||||||
|
# use_flaresolverr'ı False yapma, gerçek isteklerde tekrar dene (ama timeout kısa olacak)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _make_flaresolverr_request(self, url: str, method: str = 'GET', **kwargs) -> Optional:
|
def _make_flaresolverr_request(self, url: str, method: str = 'GET', **kwargs) -> Optional:
|
||||||
@@ -94,7 +99,20 @@ class TranscriptExtractor:
|
|||||||
import requests
|
import requests
|
||||||
import json
|
import json
|
||||||
|
|
||||||
# FlareSolverr API isteği
|
# FlareSolverr API isteği - GET veya POST
|
||||||
|
if method.upper() == 'POST':
|
||||||
|
flaresolverr_payload = {
|
||||||
|
"cmd": "request.post",
|
||||||
|
"url": url,
|
||||||
|
"maxTimeout": 60000, # 60 saniye timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
# POST data'sını ekle
|
||||||
|
if 'data' in kwargs:
|
||||||
|
flaresolverr_payload["postData"] = kwargs['data']
|
||||||
|
elif 'json' in kwargs:
|
||||||
|
flaresolverr_payload["postData"] = json.dumps(kwargs['json'])
|
||||||
|
else:
|
||||||
flaresolverr_payload = {
|
flaresolverr_payload = {
|
||||||
"cmd": "request.get",
|
"cmd": "request.get",
|
||||||
"url": url,
|
"url": url,
|
||||||
@@ -108,59 +126,81 @@ class TranscriptExtractor:
|
|||||||
|
|
||||||
logger.debug(f"[FLARESOLVERR] İstek gönderiliyor: {url[:50]}...")
|
logger.debug(f"[FLARESOLVERR] İstek gönderiliyor: {url[:50]}...")
|
||||||
|
|
||||||
|
# FlareSolverr timeout'unu kısalt (erişilemezse hemen normal isteğe geç)
|
||||||
response = requests.post(
|
response = requests.post(
|
||||||
self.flaresolverr_url,
|
self.flaresolverr_url,
|
||||||
json=flaresolverr_payload,
|
json=flaresolverr_payload,
|
||||||
timeout=65 # FlareSolverr timeout'undan biraz fazla
|
timeout=10 # 10 saniye timeout (erişilemezse hemen normal isteğe geç)
|
||||||
)
|
)
|
||||||
|
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
result = response.json()
|
result = response.json()
|
||||||
if result.get('status') == 'ok':
|
if result.get('status') == 'ok':
|
||||||
solution = result.get('solution', {})
|
solution = result.get('solution', {})
|
||||||
# FlareSolverr response formatı: solution.status HTTP status code, solution.response HTML içerik
|
# FlareSolverr response formatı: solution.status HTTP status code, solution.response içerik (HTML veya JSON)
|
||||||
status_code = solution.get('status', 200)
|
status_code = solution.get('status', 200)
|
||||||
html = solution.get('response', '')
|
response_content = solution.get('response', '')
|
||||||
headers = solution.get('headers', {})
|
headers = solution.get('headers', {})
|
||||||
|
|
||||||
# Response objesi oluştur (requests.Response benzeri)
|
# Response objesi oluştur (requests.Response benzeri)
|
||||||
class FlareSolverrResponse:
|
class FlareSolverrResponse:
|
||||||
def __init__(self, status_code, text, headers, url):
|
def __init__(self, status_code, text, headers, url, is_post=False):
|
||||||
self.status_code = status_code
|
self.status_code = status_code
|
||||||
self.text = text
|
self.text = text
|
||||||
self.content = text.encode('utf-8') if isinstance(text, str) else text
|
self.content = text.encode('utf-8') if isinstance(text, str) else text
|
||||||
self.headers = headers if headers else {}
|
self.headers = headers if headers else {}
|
||||||
self.url = url
|
self.url = url
|
||||||
self.ok = 200 <= status_code < 300
|
self.ok = 200 <= status_code < 300
|
||||||
|
self.is_post = is_post # POST isteği mi?
|
||||||
|
|
||||||
def json(self):
|
def json(self):
|
||||||
import json
|
import json
|
||||||
try:
|
try:
|
||||||
|
# POST istekleri genellikle JSON döndürür
|
||||||
|
if self.is_post:
|
||||||
|
logger.debug(f"[FLARESOLVERR] POST response JSON parse ediliyor...")
|
||||||
|
|
||||||
return json.loads(self.text)
|
return json.loads(self.text)
|
||||||
except:
|
except json.JSONDecodeError as e:
|
||||||
|
logger.error(f"[FLARESOLVERR] ❌ JSON parse hatası: {e}")
|
||||||
|
logger.error(f"[FLARESOLVERR] İçerik (ilk 900 karakter): {self.text[:900]}")
|
||||||
|
return {}
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"[FLARESOLVERR] ❌ JSON parse beklenmeyen hata: {type(e).__name__} - {str(e)}")
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
logger.info(f"[FLARESOLVERR] ✅ İstek başarılı: HTTP {status_code}, {len(html)} byte içerik")
|
is_post_request = method.upper() == 'POST'
|
||||||
|
content_size = len(response_content)
|
||||||
|
logger.info(f"[FLARESOLVERR] ✅ İstek başarılı: HTTP {status_code}, {content_size} byte içerik ({'POST' if is_post_request else 'GET'})")
|
||||||
|
|
||||||
# Debug: HTML içeriğinin ilk 500 karakterini logla
|
# Debug: İçeriğin ilk 500 karakterini logla
|
||||||
logger.debug(f"[FLARESOLVERR] HTML önizleme (ilk 500 karakter): {html[:500]}")
|
logger.debug(f"[FLARESOLVERR] İçerik önizleme (ilk 500 karakter): {response_content[:500]}")
|
||||||
|
|
||||||
# Debug: HTML'de transcript ile ilgili pattern'leri kontrol et
|
# GET istekleri için HTML analizi (POST istekleri genellikle JSON)
|
||||||
|
if not is_post_request:
|
||||||
import re
|
import re
|
||||||
if 'ytInitialPlayerResponse' in html or 'ytInitialData' in html:
|
if 'ytInitialPlayerResponse' in response_content or 'ytInitialData' in response_content:
|
||||||
logger.debug(f"[FLARESOLVERR] ✅ YouTube player response bulundu HTML'de")
|
logger.debug(f"[FLARESOLVERR] ✅ YouTube player response bulundu HTML'de")
|
||||||
else:
|
else:
|
||||||
logger.warning(f"[FLARESOLVERR] ⚠️ YouTube player response bulunamadı HTML'de")
|
logger.warning(f"[FLARESOLVERR] ⚠️ YouTube player response bulunamadı HTML'de")
|
||||||
|
|
||||||
# Debug: Transcript endpoint URL'lerini ara
|
# Debug: Transcript endpoint URL'lerini ara
|
||||||
transcript_urls = re.findall(r'https?://[^"\s]+timedtext[^"\s]*', html)
|
transcript_urls = re.findall(r'https?://[^"\s]+timedtext[^"\s]*', response_content)
|
||||||
if transcript_urls:
|
if transcript_urls:
|
||||||
logger.debug(f"[FLARESOLVERR] ✅ Transcript URL'leri bulundu: {len(transcript_urls)} adet")
|
logger.debug(f"[FLARESOLVERR] ✅ Transcript URL'leri bulundu: {len(transcript_urls)} adet")
|
||||||
logger.debug(f"[FLARESOLVERR] İlk transcript URL: {transcript_urls[0][:100]}...")
|
logger.debug(f"[FLARESOLVERR] İlk transcript URL: {transcript_urls[0][:100]}...")
|
||||||
else:
|
else:
|
||||||
logger.warning(f"[FLARESOLVERR] ⚠️ Transcript URL'leri bulunamadı HTML'de")
|
logger.warning(f"[FLARESOLVERR] ⚠️ Transcript URL'leri bulunamadı HTML'de")
|
||||||
|
else:
|
||||||
|
# POST istekleri için JSON kontrolü
|
||||||
|
try:
|
||||||
|
import json
|
||||||
|
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")
|
||||||
|
|
||||||
return FlareSolverrResponse(status_code, html, headers, url)
|
return FlareSolverrResponse(status_code, response_content, headers, url, is_post=is_post_request)
|
||||||
else:
|
else:
|
||||||
error = result.get('message', 'Unknown error')
|
error = result.get('message', 'Unknown error')
|
||||||
logger.error(f"[FLARESOLVERR] ❌ FlareSolverr hatası: {error}")
|
logger.error(f"[FLARESOLVERR] ❌ FlareSolverr hatası: {error}")
|
||||||
@@ -238,7 +278,10 @@ class TranscriptExtractor:
|
|||||||
return PatchedResponse(flaresolverr_response)
|
return PatchedResponse(flaresolverr_response)
|
||||||
else:
|
else:
|
||||||
logger.debug(f"[FLARESOLVERR] FlareSolverr yanıt vermedi, normal istek deneniyor")
|
logger.debug(f"[FLARESOLVERR] FlareSolverr yanıt vermedi, normal istek deneniyor")
|
||||||
elif extractor_instance.use_flaresolverr and ('youtube.com' in url or 'youtu.be' in url):
|
elif extractor_instance.use_flaresolverr and is_video_page and not extractor_instance.flaresolverr_available:
|
||||||
|
# FlareSolverr erişilemiyor, normal istek yap
|
||||||
|
logger.debug(f"[FLARESOLVERR] FlareSolverr erişilemiyor, normal istek yapılıyor: {url[:50]}...")
|
||||||
|
elif extractor_instance.use_flaresolverr and ('youtube.com' in url or 'youtu.be' in url) and '/api/' in url:
|
||||||
# Transcript API endpoint'leri için FlareSolverr kullanma, sadece header'ları ekle
|
# Transcript API endpoint'leri için FlareSolverr kullanma, sadece header'ları ekle
|
||||||
logger.debug(f"[FLARESOLVERR] Transcript API endpoint'i tespit edildi, FlareSolverr atlanıyor: {url[:50]}...")
|
logger.debug(f"[FLARESOLVERR] Transcript API endpoint'i tespit edildi, FlareSolverr atlanıyor: {url[:50]}...")
|
||||||
|
|
||||||
@@ -251,10 +294,57 @@ class TranscriptExtractor:
|
|||||||
|
|
||||||
def patched_post(session_self, url, **kwargs):
|
def patched_post(session_self, url, **kwargs):
|
||||||
"""requests.Session.post'i patch et - header'ları ekle ve FlareSolverr kullan"""
|
"""requests.Session.post'i patch et - header'ları ekle ve FlareSolverr kullan"""
|
||||||
# POST istekleri için FlareSolverr kullanma (genellikle API endpoint'leri)
|
# YouTube API endpoint'leri için FlareSolverr kullan (youtubei/v1/player gibi)
|
||||||
# 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)
|
||||||
if extractor_instance.use_flaresolverr and ('youtube.com' in url or 'youtu.be' in url):
|
|
||||||
logger.debug(f"[FLARESOLVERR] POST isteği tespit edildi, FlareSolverr atlanıyor (sadece header'lar): {url[:50]}...")
|
# 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]}...")
|
||||||
|
|
||||||
# Normal istek (header'ları ekle)
|
# Normal istek (header'ları ekle)
|
||||||
headers = kwargs.get('headers', {})
|
headers = kwargs.get('headers', {})
|
||||||
|
|||||||
Reference in New Issue
Block a user