Download Chinese ebooks from multiple sources with automatic fallback and format conversion.
bash
# Single book download (multi-source fallback)
python scripts/download_book.py --title "超越百岁" --author "彼得·阿提亚"
# Multi-source batch download (A→B→C fallback + EPUB→PDF conversion)
python scripts/multi_source_download.py ~/Books/
# Search Anna's Archive directly
python scripts/search_source_c.py "书名" "作者"
# Convert EPUB to PDF
python scripts/epub_to_pdf.py book.epub book.pdf
SourceCoverageLimitNotesSource A (online book library)~100%NonePrimary — high coverage for popular Chinese booksSource B (secondary library)~8%NoneFallback for missing titlesSource C (Anna's Archive)WideRate-limitedLast resort — uses libgen.li mirrors
Note: Z-Library has been deprecated due to 10/day download limit.
The multi_source_download.py script automatically tries sources in order:
text
Source A → Source B → Source C → EPUB→PDF Conversion
Workflow per book:
Usage:
bash
# Edit BOOKS list in script, then run:
python scripts/multi_source_download.py ~/Books/
When only EPUB format is available, auto-convert using weasyprint:
bash
# Single file
python scripts/epub_to_pdf.py input.epub output.pdf
# Batch convert directory
python scripts/epub_to_pdf.py --batch ~/Books/
Requirements: ebooklib, weasyprint, CJK fonts installed.
ScriptPurposedownload_book.pyPrimary download from Source Asearch_secondary_source.pySource B search & downloadsearch_source_c.pyAnna's Archive search & downloadbatch_download.pyBatch download from JSON listmulti_source_download.pyMulti-source A→B→C fallbackepub_to_pdf.pyEPUB/MOBI to PDF conversionanna_iso_batch.shAnna's Archive isolated batch (one process per book)
text
Search → Get file host link → Decrypt → Wait countdown → API fetch → curl download → Extract ZIP
Search the primary library for the book title. Navigate to download page, extract file host URL and password.
Navigate to file host URL, enter password, click decrypt.
File hosting service requires countdown before download. Do not skip.
Get page variables:
javascript
JSON.stringify({api_server, userid, file_id, share_id, file_chk, start_time, wait_seconds, verifycode})
Call API:
javascript
(async () => {
var url = api_server + '/get_file_url.php?uid=' + userid
+ '&fid=' + file_id + '&folder_id=0&share_id=' + share_id
+ '&file_chk=' + file_chk + '&start_time=' + start_time
+ '&wait_seconds=' + wait_seconds + '&mb=0&app=0&acheck=0'
+ '&verifycode=' + verifycode + '&rd=' + Math.random();
var headers = typeof getAjaxHeaders === 'function' ? getAjaxHeaders() : {};
var resp = await fetch(url, {headers: headers});
return JSON.stringify(await resp.json());
})()
Response code: 200 → downurl is real URL.
bash
curl -L -o "book.zip" "DOWNURL" \
-H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)" \
--max-time 1200
python
import zipfile
with zipfile.ZipFile('book.zip', 'r') as z:
for info in z.infolist():
try:
name = info.filename.encode('cp437').decode('gbk')
except:
name = info.filename
ext = os.path.splitext(name)[1].lower()
if ext in ('.epub', '.azw3', '.mobi', '.pdf', '.txt'):
data = z.read(info.filename)
with open(os.path.basename(name), 'wb') as f:
f.write(data)
When a book title is long or contains multiple names (e.g. box sets):
Examples:
FlagDescription--format pdfPDF only (default, preferred for NotebookLM)--format epubEPUB only--format mobiMOBI only--format azw3AZW3 only--format anyAccept any available format
bash
python scripts/batch_download.py --book-list books.json --output-dir ~/Books/
JSON format:
json
[
{"title": "超越百岁", "file_url": "<file_host_url>", "password": "<password>"}
]
Features: resume via _progress.json, skip existing, rate limiting.
ProblemSolutionIP blockingUse browser tool, not web_fetchLink 404Link expired, re-searchAPI non-200Re-navigate and re-decryptDownload is HTMLURL expired, fresh API call neededZIP filenames garbledUse Python cp437→gbk, not unzipTimeout on large filesIncrease --max-time to 1200Anna's Archive blockedTry different mirror, use anna_iso_batch.sh