93 lines
3.1 KiB
Python
93 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
|
"""수령한 생활 수기집 목록의 Google Drive 공유 원본을 다운로드한다."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
FILE_ID = re.compile(r"drive\.google\.com/file/d/([^/]+)")
|
|
FOLDER_ID = re.compile(r"drive\.google\.com/drive/folders/([^/?]+)")
|
|
|
|
|
|
def parse_args() -> argparse.Namespace:
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("manifest", type=Path)
|
|
parser.add_argument("--out-dir", type=Path, required=True)
|
|
parser.add_argument("--report", type=Path, required=True)
|
|
return parser.parse_args()
|
|
|
|
|
|
def drive_kind(url: str) -> tuple[str, str] | None:
|
|
if match := FILE_ID.search(url):
|
|
return "file", match.group(1)
|
|
if match := FOLDER_ID.search(url):
|
|
return "folder", match.group(1)
|
|
return None
|
|
|
|
|
|
def main() -> int:
|
|
args = parse_args()
|
|
try:
|
|
import gdown
|
|
from openpyxl import load_workbook
|
|
except ImportError:
|
|
print("gdown과 openpyxl이 필요합니다.", file=sys.stderr)
|
|
return 2
|
|
|
|
workbook = load_workbook(args.manifest, read_only=False, data_only=False)
|
|
sheet = workbook.worksheets[0]
|
|
results = []
|
|
args.out_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
for rownum in range(3, sheet.max_row + 1):
|
|
cell = sheet.cell(row=rownum, column=10)
|
|
url = cell.hyperlink.target if cell.hyperlink else ""
|
|
parsed = drive_kind(url or "")
|
|
if not parsed:
|
|
continue
|
|
kind, drive_id = parsed
|
|
target = args.out_dir / f"source_{rownum:03d}"
|
|
target.mkdir(parents=True, exist_ok=True)
|
|
result = {
|
|
"row": rownum,
|
|
"kind": kind,
|
|
"drive_id": drive_id,
|
|
"url": url,
|
|
"label": str(cell.value or ""),
|
|
"status": "failed",
|
|
"files": [],
|
|
}
|
|
try:
|
|
if kind == "folder":
|
|
gdown.download_folder(
|
|
url=url, output=str(target), quiet=False, remaining_ok=True,
|
|
)
|
|
else:
|
|
gdown.download(id=drive_id, output=str(target) + "/", quiet=False)
|
|
files = sorted(str(p.relative_to(args.out_dir)) for p in target.rglob("*") if p.is_file())
|
|
result["files"] = files
|
|
result["status"] = "downloaded" if files else "empty"
|
|
except Exception as exc: # noqa: BLE001
|
|
result["error"] = str(exc)
|
|
results.append(result)
|
|
|
|
report = {
|
|
"manifest": args.manifest.name,
|
|
"drive_links": len(results),
|
|
"downloaded": sum(r["status"] == "downloaded" for r in results),
|
|
"failed_or_empty": sum(r["status"] != "downloaded" for r in results),
|
|
"results": results,
|
|
}
|
|
args.report.parent.mkdir(parents=True, exist_ok=True)
|
|
args.report.write_text(json.dumps(report, ensure_ascii=False, indent=2), encoding="utf-8")
|
|
print(json.dumps({k: v for k, v in report.items() if k != "results"}, ensure_ascii=False))
|
|
return 0 if report["downloaded"] else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|