v0.5.3: Add manual browser path setting for Zendriver in Docker
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
title: "애니 다운로더"
|
title: "애니 다운로더"
|
||||||
version: "0.5.3"
|
version: "0.5.4"
|
||||||
package_name: "anime_downloader"
|
package_name: "anime_downloader"
|
||||||
developer: "projectdx"
|
developer: "projectdx"
|
||||||
description: "anime downloader"
|
description: "anime downloader"
|
||||||
|
|||||||
@@ -35,10 +35,15 @@ DAEMON_PORT: int = 19876
|
|||||||
browser: Optional[Any] = None
|
browser: Optional[Any] = None
|
||||||
browser_lock: Lock = Lock()
|
browser_lock: Lock = Lock()
|
||||||
loop: Optional[asyncio.AbstractEventLoop] = None
|
loop: Optional[asyncio.AbstractEventLoop] = None
|
||||||
|
manual_browser_path: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
def find_browser_executable() -> Optional[str]:
|
def find_browser_executable() -> Optional[str]:
|
||||||
"""시스템에서 브라우저 실행 파일 찾기 (Docker/Ubuntu 환경 대응)"""
|
\"\"\"시스템에서 브라우저 실행 파일 찾기 (Docker/Ubuntu 환경 대응)\"\"\"
|
||||||
|
# 수동 설정된 경로 최우선
|
||||||
|
if manual_browser_path and os.path.exists(manual_browser_path):
|
||||||
|
return manual_browser_path
|
||||||
|
|
||||||
common_paths: List[str] = [
|
common_paths: List[str] = [
|
||||||
"/usr/bin/google-chrome",
|
"/usr/bin/google-chrome",
|
||||||
"/usr/bin/google-chrome-stable",
|
"/usr/bin/google-chrome-stable",
|
||||||
@@ -277,7 +282,17 @@ def signal_handler(sig: int, frame: Any) -> None:
|
|||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == \"__main__\":
|
||||||
|
# 인자 처리
|
||||||
|
import argparse
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument(\"--browser_path\", type=str, default=None)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.browser_path:
|
||||||
|
manual_browser_path = args.browser_path
|
||||||
|
log_debug(f\"[ZendriverDaemon] Manual browser path set: {manual_browser_path}\")
|
||||||
|
|
||||||
# 시그널 핸들러 등록
|
# 시그널 핸들러 등록
|
||||||
signal.signal(signal.SIGINT, signal_handler)
|
signal.signal(signal.SIGINT, signal_handler)
|
||||||
signal.signal(signal.SIGTERM, signal_handler)
|
signal.signal(signal.SIGTERM, signal_handler)
|
||||||
|
|||||||
@@ -14,8 +14,12 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
|
|
||||||
def find_browser_executable():
|
def find_browser_executable(manual_path=None):
|
||||||
"""시스템에서 브라우저 실행 파일 찾기 (Docker/Ubuntu 환경 대응)"""
|
\"\"\"시스템에서 브라우저 실행 파일 찾기 (Docker/Ubuntu 환경 대응)\"\"\"
|
||||||
|
# 수동 설정 시 우선
|
||||||
|
if manual_path and os.path.exists(manual_path):
|
||||||
|
return manual_path
|
||||||
|
|
||||||
common_paths = [
|
common_paths = [
|
||||||
"/usr/bin/google-chrome",
|
"/usr/bin/google-chrome",
|
||||||
"/usr/bin/google-chrome-stable",
|
"/usr/bin/google-chrome-stable",
|
||||||
@@ -38,8 +42,8 @@ def find_browser_executable():
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
async def fetch_html(url: str, timeout: int = 60) -> dict:
|
async def fetch_html(url: str, timeout: int = 60, browser_path: str = None) -> dict:
|
||||||
"""Zendriver로 HTML 페칭"""
|
\"\"\"Zendriver로 HTML 페칭\"\"\"
|
||||||
try:
|
try:
|
||||||
import zendriver as zd
|
import zendriver as zd
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
@@ -51,7 +55,7 @@ async def fetch_html(url: str, timeout: int = 60) -> dict:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# 실행 가능한 브라우저 찾기
|
# 실행 가능한 브라우저 찾기
|
||||||
exec_path = find_browser_executable()
|
exec_path = find_browser_executable(browser_path)
|
||||||
|
|
||||||
# 브라우저 시작
|
# 브라우저 시작
|
||||||
if exec_path:
|
if exec_path:
|
||||||
@@ -98,9 +102,10 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
target_url = sys.argv[1]
|
target_url = sys.argv[1]
|
||||||
timeout_sec = int(sys.argv[2]) if len(sys.argv) > 2 else 60
|
timeout_sec = int(sys.argv[2]) if len(sys.argv) > 2 else 60
|
||||||
|
manual_path = sys.argv[3] if len(sys.argv) > 3 else None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
res = asyncio.run(fetch_html(target_url, timeout_sec))
|
res = asyncio.run(fetch_html(target_url, timeout_sec, manual_path))
|
||||||
print(json.dumps(res, ensure_ascii=False))
|
print(json.dumps(res, ensure_ascii=False))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(json.dumps({"success": False, "error": str(e), "html": "", "elapsed": 0}))
|
print(json.dumps({"success": False, "error": str(e), "html": "", "elapsed": 0}))
|
||||||
|
|||||||
@@ -139,7 +139,12 @@ class LogicOhli24(AnimeModuleBase):
|
|||||||
|
|
||||||
# 브라우저 존재 확인 안내
|
# 브라우저 존재 확인 안내
|
||||||
import shutil
|
import shutil
|
||||||
has_browser = any(shutil.which(cmd) for cmd in ["google-chrome", "google-chrome-stable", "chromium-browser", "chromium"])
|
browser_path = P.ModelSetting.get(\"ohli24_zendriver_browser_path\")
|
||||||
|
if browser_path and os.path.exists(browser_path):
|
||||||
|
has_browser = True
|
||||||
|
else:
|
||||||
|
has_browser = any(shutil.which(cmd) for cmd in [\"google-chrome\", \"google-chrome-stable\", \"chromium-browser\", \"chromium\"])
|
||||||
|
|
||||||
if not has_browser:
|
if not has_browser:
|
||||||
logger.warning("[Zendriver] 브라우저(Chrome/Chromium)가 시스템에 설치되어 있지 않습니다. Docker 환경에서는 직접 설치가 필요할 수 있습니다.")
|
logger.warning("[Zendriver] 브라우저(Chrome/Chromium)가 시스템에 설치되어 있지 않습니다. Docker 환경에서는 직접 설치가 필요할 수 있습니다.")
|
||||||
logger.warning("[Zendriver] Ubuntu Tip: apt-get update && apt-get install -y chromium-browser")
|
logger.warning("[Zendriver] Ubuntu Tip: apt-get update && apt-get install -y chromium-browser")
|
||||||
@@ -171,8 +176,13 @@ class LogicOhli24(AnimeModuleBase):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
# 데몬 프로세스 시작 (백그라운드)
|
# 데몬 프로세스 시작 (백그라운드)
|
||||||
|
browser_path = P.ModelSetting.get(\"ohli24_zendriver_browser_path\")
|
||||||
|
cmd = [sys.executable, daemon_script]
|
||||||
|
if browser_path:
|
||||||
|
cmd.extend([\"--browser_path\", browser_path])
|
||||||
|
|
||||||
cls.zendriver_daemon_process = subprocess.Popen(
|
cls.zendriver_daemon_process = subprocess.Popen(
|
||||||
[sys.executable, daemon_script],
|
cmd,
|
||||||
stdout=subprocess.DEVNULL,
|
stdout=subprocess.DEVNULL,
|
||||||
stderr=subprocess.DEVNULL,
|
stderr=subprocess.DEVNULL,
|
||||||
start_new_session=True
|
start_new_session=True
|
||||||
@@ -245,6 +255,7 @@ class LogicOhli24(AnimeModuleBase):
|
|||||||
"ohli24_image_url_prefix_series": "https://www.jetcloud.cc/series/",
|
"ohli24_image_url_prefix_series": "https://www.jetcloud.cc/series/",
|
||||||
"ohli24_image_url_prefix_episode": "https://www.jetcloud-list.cc/thumbnail/",
|
"ohli24_image_url_prefix_episode": "https://www.jetcloud-list.cc/thumbnail/",
|
||||||
"ohli24_discord_notify": "True",
|
"ohli24_discord_notify": "True",
|
||||||
|
"ohli24_zendriver_browser_path": "",
|
||||||
}
|
}
|
||||||
super(LogicOhli24, self).__init__(P, name=name, first_menu='setting', scheduler_desc="ohli24 자동 다운로드", setup_default=self.db_default)
|
super(LogicOhli24, self).__init__(P, name=name, first_menu='setting', scheduler_desc="ohli24 자동 다운로드", setup_default=self.db_default)
|
||||||
self.queue = None
|
self.queue = None
|
||||||
@@ -1446,7 +1457,12 @@ class LogicOhli24(AnimeModuleBase):
|
|||||||
try:
|
try:
|
||||||
import subprocess
|
import subprocess
|
||||||
import contextlib
|
import contextlib
|
||||||
script_path = os.path.join(os.path.dirname(__file__), "lib", "zendriver_ohli24.py")
|
script_path = os.path.join(os.path.dirname(__file__), \"lib\", \"zendriver_ohli24.py\")
|
||||||
|
browser_path = P.ModelSetting.get(\"ohli24_zendriver_browser_path\")
|
||||||
|
|
||||||
|
cmd = [sys.executable, script_path, url, str(timeout)]
|
||||||
|
if browser_path:
|
||||||
|
cmd.append(browser_path)
|
||||||
|
|
||||||
# gevent fork 경고 억제 (부모 프로세스 stderr 임시 리다이렉트)
|
# gevent fork 경고 억제 (부모 프로세스 stderr 임시 리다이렉트)
|
||||||
with open(os.devnull, 'w') as devnull:
|
with open(os.devnull, 'w') as devnull:
|
||||||
@@ -1454,7 +1470,7 @@ class LogicOhli24(AnimeModuleBase):
|
|||||||
sys.stderr = devnull
|
sys.stderr = devnull
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
[sys.executable, script_path, url, str(timeout)],
|
cmd,
|
||||||
capture_output=False,
|
capture_output=False,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.DEVNULL,
|
stderr=subprocess.DEVNULL,
|
||||||
|
|||||||
@@ -78,6 +78,9 @@
|
|||||||
{{ macros.setting_buttons([['global_one_execute_btn', '1회 실행']], left='1회 실행' ) }}
|
{{ macros.setting_buttons([['global_one_execute_btn', '1회 실행']], left='1회 실행' ) }}
|
||||||
<hr style="border-color: rgba(255,255,255,0.1);">
|
<hr style="border-color: rgba(255,255,255,0.1);">
|
||||||
{{ macros.setting_buttons([['global_reset_db_btn', 'DB 초기화']], left='DB정리' ) }}
|
{{ macros.setting_buttons([['global_reset_db_btn', 'DB 초기화']], left='DB정리' ) }}
|
||||||
|
<hr style="border-color: rgba(255,255,255,0.1);">
|
||||||
|
<h5 class="text-info mb-3"><i class="bi bi-browser-chrome mr-2"></i>Zendriver 설정</h5>
|
||||||
|
{{ macros.setting_input_text('ohli24_zendriver_browser_path', '브라우저 경로', value=arg.get('ohli24_zendriver_browser_path', ''), desc=['Zendriver가 사용할 Chrome/Chromium 실행 파일 경로입니다.', 'Docker 환경에서 자동 탐지에 실패할 경우 직접 입력하세요.', '예: /usr/bin/chromium-browser']) }}
|
||||||
</div>
|
</div>
|
||||||
{{ macros.m_tab_content_end() }}
|
{{ macros.m_tab_content_end() }}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user