last update

This commit is contained in:
Louis Mylle
2026-01-10 14:59:35 +01:00
parent ea4cab15c3
commit 757fc291b0
30 changed files with 22270 additions and 30 deletions

172
scripts/build_executable.py Normal file
View File

@@ -0,0 +1,172 @@
#!/usr/bin/env python3
"""
Cross-platform build script for EBoek.info Scraper
Creates a standalone executable using PyInstaller
"""
import os
import sys
import subprocess
import shutil
from pathlib import Path
def run_command(command, description):
"""Run a command and handle errors."""
print(f"{description}...")
try:
result = subprocess.run(command, shell=True, capture_output=True, text=True)
if result.returncode != 0:
print(f"✗ Error: {result.stderr}")
return False
if result.stdout.strip():
print(f" {result.stdout.strip()}")
return True
except Exception as e:
print(f"✗ Exception: {e}")
return False
def main():
"""Main build process."""
print("=" * 50)
print("🚀 EBoek.info Scraper - Executable Builder")
print("=" * 50)
print()
# Change to project root directory (parent of scripts/)
script_dir = Path(__file__).parent
project_root = script_dir.parent
os.chdir(project_root)
print(f"📂 Working from: {project_root}")
print()
# Check Python version
if sys.version_info < (3, 8):
print("✗ Error: Python 3.8+ required")
sys.exit(1)
# Check if PyInstaller is installed
try:
import PyInstaller
print(f"✓ PyInstaller {PyInstaller.__version__} found")
except ImportError:
print("→ Installing PyInstaller...")
if not run_command(f"{sys.executable} -m pip install pyinstaller", "Installing PyInstaller"):
print("✗ Failed to install PyInstaller")
sys.exit(1)
# Clean previous builds
print()
for directory in ["dist", "build"]:
if Path(directory).exists():
shutil.rmtree(directory)
print(f"✓ Cleaned {directory}/")
# Determine platform-specific settings
is_windows = sys.platform.startswith('win')
exe_name = "EBoek_Scraper.exe" if is_windows else "EBoek_Scraper"
# Build command
build_cmd = [
f"{sys.executable}", "-m", "PyInstaller",
"--onefile",
"--windowed",
"--name", "EBoek_Scraper",
# Hidden imports for PyQt5
"--hidden-import", "PyQt5.QtCore",
"--hidden-import", "PyQt5.QtGui",
"--hidden-import", "PyQt5.QtWidgets",
# Hidden imports for Selenium
"--hidden-import", "selenium",
"--hidden-import", "selenium.webdriver",
"--hidden-import", "selenium.webdriver.chrome",
"--hidden-import", "selenium.webdriver.chrome.options",
"--hidden-import", "selenium.webdriver.common.by",
# Hidden imports for our modules
"--hidden-import", "core.scraper",
"--hidden-import", "core.scraper_thread",
"--hidden-import", "core.credentials",
"--hidden-import", "gui.main_window",
"--hidden-import", "gui.login_dialog",
"--hidden-import", "gui.progress_dialog",
"--hidden-import", "utils.validators",
# Exclude unnecessary modules to reduce size
"--exclude-module", "tkinter",
"--exclude-module", "matplotlib",
"--exclude-module", "numpy",
"--exclude-module", "pandas",
# Main script
"gui_main.py"
]
print()
print("🔨 Building executable...")
print("📝 This may take a few minutes...")
print()
# Run PyInstaller
try:
result = subprocess.run(build_cmd, capture_output=True, text=True)
if result.returncode != 0:
print("✗ Build failed!")
print("Error output:")
print(result.stderr)
# Try fallback with spec file
print()
print("🔄 Trying alternative build with spec file...")
spec_cmd = [f"{sys.executable}", "-m", "PyInstaller", "scripts/eboek_scraper.spec"]
result = subprocess.run(spec_cmd, capture_output=True, text=True)
if result.returncode != 0:
print("✗ Alternative build also failed!")
print(result.stderr)
sys.exit(1)
print("✓ Build completed successfully!")
except Exception as e:
print(f"✗ Build failed with exception: {e}")
sys.exit(1)
# Check if executable was created
exe_path = Path("dist") / exe_name
if not exe_path.exists():
print(f"✗ Error: Executable not found at {exe_path}")
sys.exit(1)
# Display results
file_size = exe_path.stat().st_size / (1024 * 1024) # MB
print()
print("=" * 50)
print("🎉 BUILD SUCCESSFUL!")
print("=" * 50)
print(f"📂 Executable location: {exe_path}")
print(f"📊 File size: {file_size:.1f} MB")
print()
# Platform-specific instructions
if is_windows:
print("🪟 Windows Instructions:")
print(f" • Run: {exe_path}")
print(" • Windows may show security warning on first run")
print(" • Click 'More Info''Run Anyway' if prompted")
else:
print("🍎 macOS/Linux Instructions:")
print(f" • Run: ./{exe_path}")
print(" • macOS may show security warning on first run")
print(" • Right-click and select 'Open' to bypass Gatekeeper")
print()
print("📦 Distribution:")
print(f" • Share this single file: {exe_name}")
print(" • No Python installation required on target machine")
print(" • Includes all dependencies (PyQt5, Selenium, etc.)")
print()
print("✨ Ready for distribution!")
if __name__ == "__main__":
main()