feat: Fetch all album from an account

* add user and password parameters (not used if profile_dir is set)
* remove mandatory album_url args
* auto login with user and password
* add locale for FR and GOOGLE_LANG (default en) environment variable to switch
* add CHROME_BINARY whenever need to specify chrome binary path
* add headless compatibilty for WSL
* fix missing gp_temp after first loop
* fix unclickable "More option" button by fetching "Share" button first
This commit is contained in:
Adi3000
2025-08-14 21:31:58 +02:00
parent a79d3c96da
commit 8f0a6909e2
5 changed files with 145 additions and 19 deletions

View File

@@ -1,6 +1,6 @@
import argparse, logging, sys, time
from statistics import median
from .lib import download_albums
from .lib import download_albums, login, list_albums
BANNER = """
██████ ██████ ██████ ██
@@ -25,11 +25,13 @@ LOG_LEVELS = {
def parse_cli_args():
parser = argparse.ArgumentParser(description="Download full-res images from a Google Photos album using Selenium.")
parser.add_argument("--album-urls", nargs="+", required=True, help="Google Photos album URL(s)")
parser.add_argument("--output-dir", required=True, help="The directory to save downloaded albums")
parser.add_argument("--album-urls", nargs="+", help="Google Photos album URL(s)")
parser.add_argument("--output-dir", default=None, required=True, help="The directory to save downloaded albums")
parser.add_argument("--driver-path", default=None, help="Custom Chrome driver path")
parser.add_argument("--profile-dir", default=None, help="A Chrome user data directory for sessions, set this if you want to open non-shared links.")
parser.add_argument("--headless", action="store_true", help="Run Chrome headlessly")
parser.add_argument("--user", default=None, help="Google user login (ie. email address)")
parser.add_argument("--password", default=None, help="Google user password")
parser.add_argument("--log-level", default="INFO", help="Specifies what to include in log output. Available levels: debug, info, error, fatal")
return parser.parse_args()
@@ -52,12 +54,15 @@ def run_cli():
configure_logging(args.log_level)
all_start = time.perf_counter()
album_urls = args.album_urls
if not args.album_urls:
album_urls = list_albums(driver_path=args.driver_path, profile_dir=args.profile_dir, headless=args.headless, user=args.user, password=args.password)
successful_albums, failed_albums, album_times = download_albums(args.album_urls, args.output_dir, args.driver_path, args.profile_dir, args.headless)
successful_albums, failed_albums, album_times = download_albums(album_urls, args.output_dir, args.driver_path, args.profile_dir, args.headless)
logging.info("")
logging.info("===== DOWNLOAD STATISTICS =====")
logging.info(f"Total albums given: {len(args.album_urls)}")
logging.info(f"Total albums given: {len(album_urls)}")
logging.info(f"Successful albums ({len(successful_albums)}): {', '.join(successful_albums) or None}")
logging.info(f"Failed albums ({len(failed_albums)}): {', '.join(failed_albums) or 'None'}")
logging.info(f"Median time taken per album: {median(album_times or [0]):.2f} seconds")