o2o-plagiarism-ai/scripts/download_life_writing_drive.py

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())