"""Открыть в браузере ссылки из TXT для скачивания через браузерную сессию.""" from __future__ import annotations import argparse import time import webbrowser from pathlib import Path from urllib.parse import urlparse def read_urls(txt_file: Path) -> list[str]: """Прочитать непустые HTTP/HTTPS-ссылки, кроме комментариев с #.""" urls: list[str] = [] with txt_file.open("r", encoding="utf-8-sig") as file: for line_number, line in enumerate(file, start=1): value = line.strip() if not value or value.startswith("#"): continue if urlparse(value).scheme not in {"http", "https"}: print(f"Строка {line_number} пропущена: это не HTTP/HTTPS-ссылка") continue urls.append(value) return urls def main() -> None: parser = argparse.ArgumentParser( description="Последовательно открыть ссылки из TXT в системном браузере" ) parser.add_argument("txt_file", type=Path, help="TXT-файл: одна ссылка на строку") parser.add_argument( "--delay", type=float, default=0.2, help="Пауза между ссылками в секундах (по умолчанию 1.5)", ) parser.add_argument( "--start", type=int, default=1, help="Начать с указанного номера строки списка (по умолчанию 1)", ) parser.add_argument( "--limit", type=int, help="Открыть не больше указанного числа ссылок", ) args = parser.parse_args() if not args.txt_file.is_file(): parser.error(f"файл не найден: {args.txt_file}") if args.delay < 0: parser.error("--delay не может быть отрицательным") if args.start < 1: parser.error("--start должен быть не меньше 1") if args.limit is not None and args.limit < 1: parser.error("--limit должен быть не меньше 1") all_urls = read_urls(args.txt_file) urls = all_urls[args.start - 1 :] if args.limit is not None: urls = urls[: args.limit] if not urls: raise SystemExit("Нет ссылок для открытия.") print( f"Будет открыто ссылок: {len(urls)} из {len(all_urls)}. " f"Начало с номера: {args.start}." ) print( "Браузер сохраняет оригинальные имена и расширения. " "Не закрывайте его до завершения." ) failed = 0 for offset, url in enumerate(urls): number = args.start + offset try: # new=0 просит браузер использовать существующее окно. Для download- # ответа браузер обычно начинает загрузку, не оставляя новую вкладку. opened = webbrowser.open(url, new=0, autoraise=False) if not opened: raise RuntimeError("системный браузер не принял ссылку") print(f"[{offset + 1}/{len(urls)}] Открыта ссылка №{number}") except Exception as error: failed += 1 print(f"[{offset + 1}/{len(urls)}] ОШИБКА №{number}: {error}") if offset + 1 < len(urls): time.sleep(args.delay) print(f"Готово. Передано браузеру: {len(urls) - failed}, ошибок: {failed}.") if failed: raise SystemExit(1) if __name__ == "__main__": main()