# scripts.zotero-notebooklm-csvtopdfs **Repository Path**: ysl2/scripts.zotero-notebooklm-csvtopdfs ## Basic Information - **Project Name**: scripts.zotero-notebooklm-csvtopdfs - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-03-01 - **Last Updated**: 2026-03-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ๐Ÿ“š Zotero arXiv CSV PDF Downloader This project reads records from a Zotero-exported `main.csv`, downloads arXiv PDFs in batch, and uses a deterministic filename rule to avoid duplicate downloads across runs. ## โœจ Features - ๐Ÿ”Ž Processes arXiv URLs only - โญ๏ธ Skips non-arXiv records and prints them in the final summary - ๐Ÿงพ Stable and readable filename format: - `{submitted_yyyymmdd}--{normalized_title}--{normalized_doc_id}.pdf` - ๐Ÿ“… Fetches submitted/public date from arXiv metadata on each run (does not trust CSV date) - ๐Ÿงฉ Uses `.part` temporary files and atomic replace after validation - โœ… Validates PDF integrity (size, `%PDF-` header, `%%EOF` footer) - ๐Ÿ”„ Two-phase execution: - Phase 1: process records that already have `00000000` placeholder files - Phase 2: process all remaining records - โ™ป๏ธ Placeholder migration: - If a real date is later available, valid `00000000--...` files are renamed to real-date filenames - Corrupted placeholder files are deleted, never migrated - ๐Ÿงต Concurrency model: - 10 download worker threads - 1 independent poller thread for continuous placeholder migration - Around 11 active worker threads during Phase 2 ## ๐Ÿ“ฆ Requirements - ๐Ÿ Python `>=3.14` - โšก `uv` is recommended Install dependencies: ```bash uv sync ``` ## ๐Ÿงพ Input CSV Default input file: `main.csv` in project root. Required fields: - ๐Ÿ”— `Url`: paper link (only arXiv links are downloaded) - ๐Ÿท๏ธ `Title`: paper title used in filenames - ๐Ÿ”‘ `Key`: fallback name when `Title` is empty ## ๐Ÿš€ Usage ```bash uv run python main.py ``` ## ๐ŸŒ Proxy (Optional) If you use a local proxy (for example Clash): ```bash export HTTP_PROXY=http://127.0.0.1:7890 export HTTPS_PROXY=http://127.0.0.1:7890 uv run python main.py ``` ## ๐Ÿง  Filename Rule Final filename: ```text {submitted_yyyymmdd}--{normalized_title}--{normalized_doc_id}.pdf ``` - ๐Ÿ“… `submitted_yyyymmdd`: fetched from arXiv metadata - ๐Ÿงน `normalized_title`: deterministic title normalization (NFKC, illegal-char cleanup, separator compression) - ๐Ÿ†” `normalized_doc_id`: normalized arXiv id (example: `2501.12345v2 -> 2501_12345v2`) If date lookup fails temporarily, the fallback prefix is: ```text 00000000--... ``` Later runs will keep trying to migrate these placeholders to real-date filenames. ## ๐Ÿ“Š Runtime Summary The script prints these counters at the end: - โฌ‡๏ธ `Downloaded` - โญ๏ธ `Skipped` - โŒ `Failed` - ๐Ÿšซ `Non-arXiv skipped` - ๐Ÿ•’ `Date fallback (00000000)` - ๐Ÿงฎ `Total rows` If non-arXiv records exist, it also prints up to 20 skipped record entries. ## โš ๏ธ Notes - ๐Ÿ“„ This tool currently downloads arXiv PDFs only. - ๐ŸŒง๏ธ If network/proxy is unavailable, date fetch and PDF download can fail, increasing `00000000` files. - ๐Ÿ” The poller runs continuously (no sleep interval) for faster migration, which may increase CPU and request pressure. ## ๐Ÿ—‚๏ธ Project Structure - ๐Ÿง  Main script: `main.py` - ๐Ÿงช Tests: `tests/test_naming.py` ## ๐Ÿ“œ License MIT