test: windows端双向同步验证
This commit is contained in:
@@ -14,3 +14,5 @@ raw/量化/abuquant-src/
|
||||
.obsidian/workspace.json
|
||||
.obsidian/workspace-mobile.json
|
||||
.obsidian/graph.json
|
||||
raw/书籍/_ocr-md/_chunks/
|
||||
raw/书籍/_ocr-md/images/
|
||||
|
||||
@@ -4,7 +4,7 @@ b02 丁圣元--日本蜡烛图技术.pdf C:\Users\12637\Desktop\投资学习资
|
||||
b03 价值.pdf C:\Users\12637\Desktop\投资学习资料by海螺\1.经典投资书籍(优先学习)\价值.pdf 005C1248CD902A52AD3426154DDF4DEC74AEAB1CDF1FDFFF551CECDEEADF47D2 285 227923 text compiled raw/书籍/00-价值投资/价值-张磊-2020-摘编.md wiki/concepts/长期主义与价值创造.md C:\Users\12637\AppData\Local\Temp\hermes-books\txt\价值.txt 00-价值投资 张磊《价值》 28 94:第一部分 寻找价值的历程|95:第1章 价值的底色|102:第2章 价值投资启蒙|107:第3章 价值投资初试炼|113:第二部分 价值投资的哲学与修养|114:第4章 价值投资方法与哲学|125:第5章 价值投资者的自我修养|134:第三部分 价值投资的创新框架|135:第6章 与伟大格局观者同行|141:第7章 持续创造价值的卓越组织|149:第8章 产业变革中的价值投资|155:第9章 价值投资的实践探索|159:第10章 永远追求丰富而有益的人生|164:附录 我的演讲和文章|8650:第一部分 寻找价值的历程|8651:第1章 价值的底色|8655:第2章 价值投资启蒙|8660:第3章 价值投资初试炼|8669:第二部分 价值投资的哲学与修养|8670:第4章 价值投资方法与哲学|8678:第5章 价值投资者的自我修养|8687:第三部分 价值投资的创新框架|8688:第6章 与伟大格局观者同行|8697:第7章 持续创造价值的卓越组织|8702:第8章 产业变革中的价值投资|8708:第9章 价值投资的实践探索|8715:第10章 永远追求丰富而有益的人生|8720:附录 我的演讲和文章
|
||||
b04 投资中不简单的事(高清).pdf C:\Users\12637\Desktop\投资学习资料by海螺\1.经典投资书籍(优先学习)\投资中不简单的事(高清).pdf FE60096B451CAB878DD3E18EA655E6020FC9504D08108A0DD03DC5761D109A08 335 6030 scan compiled raw/书籍/05-投资理念/投资中不简单的事-高毅资产-2018-摘编.md wiki/concepts/基本面投资研究框架.md C:\Users\12637\AppData\Local\Temp\hermes-books\txt\b04.txt 05-投资理念 云端OCR(PP-OCRv6) 335页全部成功 3 273:第一篇思想篇|2608:第二篇实战篇|6809:第三篇成长篇
|
||||
b05 可转债投资魔法书(第2版).pdf C:\Users\12637\Desktop\投资学习资料by海螺\1.经典投资书籍(优先学习)\可转债投资魔法书(第2版).pdf 0C89C399B406AEED380D7F364652E43509BAB5C79004C8C307A2EDBB3C28A433 293 0 scan compiled raw/书籍/03-可转债/可转债投资魔法书-安道全-第2版-摘编.md wiki/concepts/可转债投资框架.md C:\Users\12637\AppData\Local\Temp\hermes-books\txt\b05.txt 03-可转债 云端OCR(PP-OCRv6) 293页全部成功 8 198:第1章|213:第2章|256:第3章|291:第4章|337:第5章|383:第6章|441:第7章|850:第8章
|
||||
b06 期货市场技术分析 作者(美)约翰·墨菲(John J.Murphy)着 丁圣元译.pdf C:\Users\12637\Desktop\投资学习资料by海螺\1.经典投资书籍(优先学习)\期货市场技术分析 作者(美)约翰·墨菲(John J.Murphy)着 丁圣元译.pdf 6944E089001D4AA9061CCDA1B0088B4B2669BA9F0E93C2B1A4467181E6EF9CF9 546 9842 scan compiled raw/书籍/01-技术分析/期货市场技术分析-约翰墨菲-摘编.md wiki/concepts/期货技术分析体系.md C:\Users\12637\AppData\Local\Temp\hermes-books\txt\b06.txt 01-技术分析 云端OCR(PP-OCRv6) 546页全部成功 16 108:第1章 技术分析理论基础|120:第2章 道氏理论|123:第3章 图表简介|125:第4章 趋势的基本概念|132:第5章 主要反转形态|135:第6章 持续形态|142:第7章 交易量和持仓兴趣|146:第8章 长期图表和商品指数|149:第9章 移动平均线|152:第10章 摆动指数和相反意见理论|155:第11章 日内点数图|158:第12章 三点转向和优化点数图|162:第13章 艾略特波浪理论|164:第14章 时间周期|166:第15章 计算机和交易系统|168:第16章 资金管理和交易策略
|
||||
b06 期货市场技术分析 作者(美)约翰·墨菲(John J.Murphy)着 丁圣元译.pdf C:\Users\12637\Desktop\投资学习资料by海螺\1.经典投资书籍(优先学习)\期货市场技术分析 作者(美)约翰·墨菲(John J.Murphy)着 丁圣元译.pdf 6944E089001D4AA9061CCDA1B0088B4B2669BA9F0E93C2B1A4467181E6EF9CF9 546 9842 scan compiled raw/书籍/01-技术分析/期货市场技术分析-约翰墨菲-摘编.md wiki/concepts/期货技术分析体系.md C:\Users\12637\AppData\Local\Temp\hermes-books\txt\b06.txt 01-技术分析 云端OCR(PP-OCRv6) 546页全部成功;OCR全文md:raw/书籍/_ocr-md/期货市场技术分析-约翰墨菲-OCR全文.md(PaddleOCR-VL-1.6 546页) 16 108:第1章 技术分析理论基础|120:第2章 道氏理论|123:第3章 图表简介|125:第4章 趋势的基本概念|132:第5章 主要反转形态|135:第6章 持续形态|142:第7章 交易量和持仓兴趣|146:第8章 长期图表和商品指数|149:第9章 移动平均线|152:第10章 摆动指数和相反意见理论|155:第11章 日内点数图|158:第12章 三点转向和优化点数图|162:第13章 艾略特波浪理论|164:第14章 时间周期|166:第15章 计算机和交易系统|168:第16章 资金管理和交易策略
|
||||
b07 攻守:可转债投资实用手册(高清).pdf C:\Users\12637\Desktop\投资学习资料by海螺\1.经典投资书籍(优先学习)\攻守:可转债投资实用手册(高清).pdf 0ECB81ABF427A475C9E33C842345C38CCD1EBBD1F75DAC341079A5AE977939C6 140 72771 text compiled raw/书籍/03-可转债/攻守-可转债投资实用手册-2020-摘编.md wiki/concepts/可转债投资框架.md C:\Users\12637\AppData\Local\Temp\hermes-books\txt\攻守-可转债投资实用手册-高清.txt 03-可转债 有文本层 45 256:第一章 可转债Ⲵ基⸕识|265:第二章 可转债交᱃Ⲵ基本㿴则与流程|271:第三章 可转债交᱃进阶᧒讨|285:第四章 可转债交᱃策⮕|301:第五章 关于可转债Ⲵ88个䰞答|316:第一章 可转债的基础知识|320:第一节 什么是可转债|361:第二节 可转债的基本要素|651:第三节 可转债其他重要概念|741:第四节 可转债的盾与矛——债性和股性|797:第五节 抓住四要素,快速读懂可转债|980:第二章 可转债交易的基本规则与流程|984:第一节 交易基本规则|1091:第二节 可转债发行与网上申购|1182:第三节 股东如何参与可转债的优先配售|1225:第四节 可转债转股流程|1292:第三章 可转债交易进阶探讨|1293:第一节 可转债到期赎回兑付,如何缴税|1355:第二节 可转债配售中的精确算法原则|1413:第三节 可转债转股价格调整|1541:第四节 有条件赎回(强赎)的条件|1601:第五节 回售及其计数|1780:第六节 中签率测算:网上发行|1869:第七节 中签率测算:网下发行|1931:第八节 交易价格估算|2063:第九节 网下申购:机构投资者的盛宴|2144:第十节 可转债和可交债的区别|2238:第十一节 可转债VS.可交债:牛市都一样,熊市大|2337:第四章 可转债交易策略|2338:第一节 网上申购策略|2405:第二节 抢权配售策略|2509:第三节 “一手党”超额配债策略|2573:第四节 折价套利策略|2637:第五节 正股替代策略|2665:第六节 “下修博弈”策略|2791:第七节 防守之“双低”策略|2866:第八节 进攻之“低溢价”策略|2980:第九节 中庸之“摊大饼”策略|3070:第五章 关于可转债的88个问答|3978:附录
|
||||
b08 海龟交易法则 珍藏版 中信金融投资经典系列 .pdf C:\Users\12637\Desktop\投资学习资料by海螺\1.经典投资书籍(优先学习)\海龟交易法则 珍藏版 中信金融投资经典系列 .pdf F368E00500474BD1CBAEBB92B82F2CD52E16C101B3998B31BA010FD27695888D 245 146962 text compiled raw/书籍/02-交易与投机/海龟交易法则-柯蒂斯费思-摘编.md wiki/practices/趋势跟踪与海龟交易系统.md C:\Users\12637\AppData\Local\Temp\hermes-books\txt\海龟交易法则-珍藏版-中信金融投资经典系列.txt 02-交易与投机 有文本层 29 69:第一章 玩风险游戏的交易者|73:第二章 揭秘海龟思维|77:第三章 海龟培训课程|88:第四章 像海龟一样思考|94:第五章 发现系统优势|99:第六章 寻找交易时机|103:第七章 如何衡量风险|113:第八章 风险与资金管理|118:第九章 海龟式积木|121:第十章 海龟式交易系统|128:第十一章 历史测试的谎言|133:第十二章 历史测试的统计学基础|147:第十三章 防卫系统|153:第十四章 掌控自己的心魔|585:第一章|838:第二章|1153:第三章|1536:第四章|2278:第五章|2462:第六章|2663:第七章|3066:第八章|3325:第九章|3431:第十章将讨论一些使用简单回顾法的系统。|3451:第十章|4067:第十一章|4582:第十二章|5400:第十三章|5700:第十四章
|
||||
b09 股票大作手回忆录 高清 (1).pdf C:\Users\12637\Desktop\投资学习资料by海螺\1.经典投资书籍(优先学习)\股票大作手回忆录 高清 (1).pdf 9314C76902618784C0DB5A165BEB3ADA76A0D4168BF4259EB534A5A912F064F2 353 0 scan compiled raw/书籍/02-交易与投机/股票大作手回忆录-埃德温勒菲弗-摘编.md wiki/practices/利弗莫尔交易纪律.md C:\Users\12637\AppData\Local\Temp\hermes-books\txt\b09.txt 02-交易与投机 云端OCR(PP-OCRv6) 353页,1页空 24 2433:第6章|2782:第7章|2982:第8章|3500:第9章|4200:第10章|5000:第11章|5700:第12章|6300:第13章|7000:第14章|7700:第15章|8300:第16章|8900:第17章|9500:第18章|10000:第19章|10400:第20章
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
@@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
为已合并的 OCR 书籍 md 补插图:从 _chunks/*.jsonl 提取每页 markdown.images,
|
||||
下载到 <md_dir>/images/,并在每页 '<!-- page N -->' 标记后插入图片引用。
|
||||
|
||||
用法: python ocr_book_insert_images.py <book.md>
|
||||
(jsonl 缓存需在 md 同目录 _chunks/ 下,即 ocr_book_to_md.py 的产出布局)
|
||||
"""
|
||||
import json
|
||||
import glob
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import requests
|
||||
|
||||
PAGE_RE = re.compile(r"<!-- page (\d+) -->")
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print(__doc__)
|
||||
sys.exit(1)
|
||||
md_path = os.path.abspath(sys.argv[1])
|
||||
md_dir = os.path.dirname(md_path)
|
||||
chunks_dir = os.path.join(md_dir, "_chunks")
|
||||
img_root = os.path.join(md_dir, "images")
|
||||
|
||||
# 1) 按页序遍历所有 lpr,收集每页 images(全局游标推进)
|
||||
page_imgs = [] # list of dict(key->url),与页序对齐
|
||||
for jf in sorted(glob.glob(os.path.join(chunks_dir, "chunk_*.jsonl"))):
|
||||
for line in open(jf, encoding="utf-8"):
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
try:
|
||||
o = json.loads(line)
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
for res in (o.get("result") or {}).get("layoutParsingResults") or []:
|
||||
imgs = (res.get("markdown") or {}).get("images") or {}
|
||||
page_imgs.append(imgs)
|
||||
print(f"pages from jsonl: {len(page_imgs)}")
|
||||
|
||||
# 2) 下载(同 URL 去重),保存到 images/<key>
|
||||
os.makedirs(img_root, exist_ok=True)
|
||||
url_to_key = {}
|
||||
n_dl = n_skip = n_fail = 0
|
||||
for pidx, imgs in enumerate(page_imgs, 1):
|
||||
for key, url in imgs.items():
|
||||
dst = os.path.join(img_root, key)
|
||||
if url in url_to_key:
|
||||
n_skip += 1
|
||||
continue
|
||||
if os.path.exists(dst) and os.path.getsize(dst) > 0:
|
||||
url_to_key[url] = key # 已下载过,仅登记去重
|
||||
n_skip += 1
|
||||
continue
|
||||
try:
|
||||
os.makedirs(os.path.dirname(dst), exist_ok=True)
|
||||
r = requests.get(url, timeout=60)
|
||||
if r.status_code != 200:
|
||||
raise RuntimeError(f"HTTP {r.status_code}")
|
||||
with open(dst, "wb") as f:
|
||||
f.write(r.content)
|
||||
url_to_key[url] = key
|
||||
n_dl += 1
|
||||
print(f" [page {pidx}] dl {key} ({len(r.content)} B)")
|
||||
except Exception as e:
|
||||
n_fail += 1
|
||||
print(f" [page {pidx}] FAIL {key}: {e}")
|
||||
print(f"downloaded: {n_dl}, dedup-skip: {n_skip}, failed: {n_fail}")
|
||||
|
||||
# 3) 读 md,按页补齐图片引用(幂等):
|
||||
# VL 的 markdown.text 自带 HTML <img src="imgs/xxx.jpg">,路径需修为 images/imgs/;
|
||||
# 仅对 text 中未出现的图(images 字段有但 text 无引用)插入 markdown 引用,避免双图。
|
||||
with open(md_path, encoding="utf-8") as f:
|
||||
md_text = f.read()
|
||||
# 修 VL 原生 HTML 路径(幂等:已修的 images/imgs/ 不再变)
|
||||
md_text = re.sub(r'(<img src=")imgs/', r"\1images/imgs/", md_text)
|
||||
# 已有引用集合(HTML 或 markdown 形式,均以 imgs/<key> 结尾)
|
||||
have = set(re.findall(r"images/imgs/([^\")\s]+\.jpg)", md_text))
|
||||
lines = md_text.split("\n")
|
||||
out = []
|
||||
page_no = 0
|
||||
inserted = 0
|
||||
for line in lines:
|
||||
out.append(line)
|
||||
m = PAGE_RE.search(line)
|
||||
if m:
|
||||
page_no = int(m.group(1))
|
||||
imgs = page_imgs[page_no - 1] if page_no - 1 < len(page_imgs) else {}
|
||||
for i, (key, _url) in enumerate(imgs.items(), 1):
|
||||
rel = key.replace("\\", "/")
|
||||
if os.path.basename(key) in have: # key 形如 imgs/xxx.jpg,have 存 basename
|
||||
continue # text 已有 HTML 引用,不重复
|
||||
out.append(f"")
|
||||
have.add(os.path.basename(key))
|
||||
inserted += 1
|
||||
with open(md_path, "w", encoding="utf-8") as f:
|
||||
f.write("\n".join(out))
|
||||
print(f"inserted {inserted} missing image refs into {md_path}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,181 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
书籍扫描件批量 OCR -> 单本 Markdown 全文版(PaddleOCR-VL-1.6 整页 Markdown)。
|
||||
|
||||
背景:PaddleOCR v2 jobs API 单文件 100 页截断,整本书需按 100 页拆片提交;
|
||||
VL-1.6 模型返回每页 layoutParsingResults[].markdown.text(整页 Markdown,
|
||||
含表格/版面还原)。本脚本把全书合并为一份 .md 存档(raw/书籍/_ocr-md/)。
|
||||
|
||||
Usage:
|
||||
python ocr_book_to_md.py <input.pdf> <output.md> [--pages 100] [--keep-chunks]
|
||||
|
||||
流程:
|
||||
1. fitz 拆片(默认每 100 页一片,临时 PDF 存 <out_dir>/_chunks/)
|
||||
2. 每片提交 PaddleOCR-VL-1.6 job 并轮询(失败自动重试 2 次)
|
||||
3. done 后下载 jsonl 缓存到 _chunks/chunk_XX.jsonl(已存在则跳过=断点续跑)
|
||||
4. 解析 jsonl 中 markdown 文本,按页序合并为 output.md
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import requests
|
||||
import fitz # PyMuPDF
|
||||
|
||||
JOB_URL = "https://paddleocr.aistudio-app.com/api/v2/ocr/jobs"
|
||||
MODEL = "PaddleOCR-VL-1.6"
|
||||
OPTIONAL = {"useDocOrientationClassify": False, "useDocUnwarping": False, "useTextlineOrientation": False}
|
||||
|
||||
|
||||
def load_token():
|
||||
tok = os.environ.get("PADDLEOCR_ACCESS_TOKEN", "").strip()
|
||||
if tok:
|
||||
return tok
|
||||
env_path = os.path.join(
|
||||
os.path.expanduser("~"), "AppData", "Local",
|
||||
"Hermes Agent CN Desktop", "data", "hermes-home", ".env",
|
||||
)
|
||||
try:
|
||||
with open(env_path, encoding="utf-8") as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if line.startswith("PADDLEOCR_ACCESS_TOKEN="):
|
||||
return line.split("=", 1)[1].strip()
|
||||
except OSError:
|
||||
pass
|
||||
return ""
|
||||
|
||||
|
||||
TOKEN = load_token()
|
||||
if not TOKEN:
|
||||
print("FATAL: PADDLEOCR_ACCESS_TOKEN not found")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def submit_and_wait(pdf_path: str, headers: dict, retries: int = 2):
|
||||
"""提交一片 PDF,轮询至 done,返回 jsonl 文本。失败重试。"""
|
||||
data = {"model": MODEL, "optionalPayload": json.dumps(OPTIONAL)}
|
||||
for attempt in range(1, retries + 2):
|
||||
try:
|
||||
with open(pdf_path, "rb") as f:
|
||||
resp = requests.post(JOB_URL, headers=headers, data=data, files={"file": f}, timeout=120)
|
||||
if resp.status_code != 200:
|
||||
print(f" submit HTTP {resp.status_code}: {resp.text[:300]}")
|
||||
raise RuntimeError(f"submit failed: {resp.status_code}")
|
||||
job_id = resp.json()["data"]["jobId"]
|
||||
print(f" job={job_id} attempt={attempt}")
|
||||
while True:
|
||||
time.sleep(8)
|
||||
r = requests.get(f"{JOB_URL}/{job_id}", headers=headers, timeout=60)
|
||||
st = r.json()["data"]["state"]
|
||||
if st == "running":
|
||||
try:
|
||||
ep = r.json()["data"]["extractProgress"]["extractedPages"]
|
||||
tp = r.json()["data"]["extractProgress"]["totalPages"]
|
||||
print(f" running {ep}/{tp}")
|
||||
except KeyError:
|
||||
print(" running...")
|
||||
elif st == "done":
|
||||
jurl = r.json()["data"]["resultUrl"]["jsonUrl"]
|
||||
jr = requests.get(jurl, timeout=120)
|
||||
jr.raise_for_status()
|
||||
print(f" done ({len(jr.text)} bytes jsonl)")
|
||||
return jr.text
|
||||
elif st == "failed":
|
||||
msg = r.json()["data"].get("errorMsg", "?")
|
||||
print(f" FAILED: {msg}")
|
||||
raise RuntimeError(f"job failed: {msg}")
|
||||
except (RuntimeError, requests.RequestException) as e:
|
||||
print(f" attempt {attempt} error: {e}")
|
||||
if attempt <= retries:
|
||||
print(" retrying in 20s...")
|
||||
time.sleep(20)
|
||||
else:
|
||||
raise
|
||||
|
||||
|
||||
def parse_jsonl(jsonl_text: str):
|
||||
"""解析 jsonl -> list[page_md](按行序)。"""
|
||||
pages = []
|
||||
for line in jsonl_text.strip().split("\n"):
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
try:
|
||||
obj = json.loads(line)
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
result = obj.get("result") or {}
|
||||
# VL 模型 jsonl 分块返回:每行含 N 个 layoutParsingResults(=N 页),
|
||||
# 每个 lpr 的 markdown.text 即一页;dataInfo.numPages 佐证块内页数。
|
||||
lpr = result.get("layoutParsingResults") or []
|
||||
for res in lpr:
|
||||
md = res.get("markdown") or {}
|
||||
t = md.get("text")
|
||||
if t:
|
||||
pages.append(t)
|
||||
return pages
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 3:
|
||||
print(__doc__)
|
||||
sys.exit(1)
|
||||
pdf_path, out_md = sys.argv[1], sys.argv[2]
|
||||
pages_per_chunk = 100
|
||||
keep_chunks = False
|
||||
if "--pages" in sys.argv:
|
||||
pages_per_chunk = int(sys.argv[sys.argv.index("--pages") + 1])
|
||||
if "--keep-chunks" in sys.argv:
|
||||
keep_chunks = True
|
||||
|
||||
base = os.path.dirname(os.path.abspath(out_md))
|
||||
chunks_dir = os.path.join(base, "_chunks")
|
||||
os.makedirs(chunks_dir, exist_ok=True)
|
||||
headers = {"Authorization": f"bearer {TOKEN}"}
|
||||
|
||||
doc = fitz.open(pdf_path)
|
||||
total = doc.page_count
|
||||
print(f"PDF pages: {total}, chunks of {pages_per_chunk}")
|
||||
|
||||
all_pages = []
|
||||
chunk_idx = 0
|
||||
for start in range(0, total, pages_per_chunk):
|
||||
end = min(start + pages_per_chunk, total)
|
||||
chunk_idx += 1
|
||||
chunk_pdf = os.path.join(chunks_dir, f"chunk_{chunk_idx:02d}_{start+1}-{end}.pdf")
|
||||
jsonl_cache = chunk_pdf.replace(".pdf", ".jsonl")
|
||||
print(f"\n=== chunk {chunk_idx}: pages {start+1}-{end} ===")
|
||||
if os.path.exists(jsonl_cache):
|
||||
print(f" cached jsonl exists, skip submit: {os.path.basename(jsonl_cache)}")
|
||||
with open(jsonl_cache, encoding="utf-8") as f:
|
||||
jsonl_text = f.read()
|
||||
else:
|
||||
if not os.path.exists(chunk_pdf):
|
||||
sub = fitz.open()
|
||||
sub.insert_pdf(doc, from_page=start, to_page=end - 1)
|
||||
sub.save(chunk_pdf, garbage=3)
|
||||
sub.close()
|
||||
print(f" split -> {os.path.basename(chunk_pdf)}")
|
||||
jsonl_text = submit_and_wait(chunk_pdf, headers)
|
||||
with open(jsonl_cache, "w", encoding="utf-8") as f:
|
||||
f.write(jsonl_text)
|
||||
pages = parse_jsonl(jsonl_text)
|
||||
print(f" parsed {len(pages)} pages")
|
||||
all_pages.extend(pages)
|
||||
if not keep_chunks:
|
||||
try:
|
||||
os.remove(chunk_pdf)
|
||||
except OSError:
|
||||
pass
|
||||
doc.close()
|
||||
|
||||
with open(out_md, "w", encoding="utf-8") as f:
|
||||
f.write(f"<!-- OCR: {os.path.basename(pdf_path)} | {MODEL} | {total} pages | {time.strftime('%Y-%m-%d %H:%M')} -->\n\n")
|
||||
for i, pg in enumerate(all_pages, 1):
|
||||
f.write(f"\n\n<!-- page {i} -->\n\n{pg.strip()}")
|
||||
print(f"\nDONE: {out_md} ({len(all_pages)} pages, {os.path.getsize(out_md)} bytes)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1 @@
|
||||
双向同步测试 2026-08-09 17:14
|
||||
Reference in New Issue
Block a user