first commit
This commit is contained in:
130
Mineru_api_client-V2.py
Normal file
130
Mineru_api_client-V2.py
Normal file
@@ -0,0 +1,130 @@
|
||||
import os
|
||||
import requests
|
||||
import zipfile
|
||||
import io
|
||||
import shutil # 【新增】用于删除非空文件夹
|
||||
import argparse # <--- 1. 确保这里导入了
|
||||
|
||||
def main():
|
||||
# 1. 配置命令行参数解析
|
||||
parser = argparse.ArgumentParser(description="Mineru PDF 转 Markdown 批量处理工具")
|
||||
|
||||
# 添加参数
|
||||
parser.add_argument("-s", "--source", type=str, default="./Papers/ORI_PDF",
|
||||
help="源 PDF 文件夹路径 (默认: ./Papers/ORI_PDF)")
|
||||
parser.add_argument("-t", "--target", type=str, default="./Papers/ORI_MD",
|
||||
help="目标 Markdown 文件夹路径 (默认: ./Papers/ORI_MD)")
|
||||
parser.add_argument("-u", "--url", type=str, default="http://10.168.1.103:4000/extract",
|
||||
help="API 服务端地址 (默认: http://10.168.1.103:4000/extract)")
|
||||
parser.add_argument("--sync", action="store_true",
|
||||
help="任务完成后是否开启反向同步清理(删除多余的输出文件夹)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# 使用解析后的参数
|
||||
url = args.url
|
||||
source_dir = args.source
|
||||
target_dir = args.target
|
||||
|
||||
# 2. 确保源目录存在,避免报错
|
||||
if not os.path.exists(source_dir):
|
||||
print(f"错误: 找不到源文件夹 '{source_dir}'")
|
||||
exit(1)
|
||||
|
||||
# 确保目标主文件夹存在
|
||||
os.makedirs(target_dir, exist_ok=True)
|
||||
|
||||
# 3. 遍历源文件夹下的所有文件进行上传处理
|
||||
for filename in os.listdir(source_dir):
|
||||
# 只处理 PDF 文件
|
||||
if not filename.lower().endswith(".pdf"):
|
||||
continue
|
||||
|
||||
file_path = os.path.join(source_dir, filename)
|
||||
# 获取去掉 .pdf 后缀的文件名
|
||||
pdf_name_no_ext = os.path.splitext(filename)[0]
|
||||
|
||||
# 对应的输出文件夹路径
|
||||
output_folder = os.path.join(target_dir, pdf_name_no_ext)
|
||||
|
||||
# ==========================================
|
||||
# 检查是否已经处理过
|
||||
# 如果输出文件夹已存在,且内部有文件,则视为已转换,直接跳过
|
||||
# ==========================================
|
||||
if os.path.exists(output_folder) and len(os.listdir(output_folder)) > 0:
|
||||
print(f"⏩ 已存在转换结果,跳过处理: {filename}")
|
||||
continue
|
||||
|
||||
print(f"正在上传并处理 {filename}...")
|
||||
|
||||
try:
|
||||
# 4. 发送请求
|
||||
with open(file_path, "rb") as f:
|
||||
files = {"file": (filename, f, "application/pdf")}
|
||||
response = requests.post(url, files=files)
|
||||
|
||||
# 5. 处理响应结果
|
||||
if response.status_code == 200:
|
||||
# 检查服务端是否返回了包含报错信息的 JSON
|
||||
if response.headers.get('content-type') == 'application/json':
|
||||
error_msg = response.json()
|
||||
print(f"❌ 服务端处理失败 ({filename}):{error_msg.get('message', '未知错误')}")
|
||||
continue # 跳过解压,处理下一个
|
||||
|
||||
# 确保该 PDF 专属的输出文件夹存在
|
||||
os.makedirs(output_folder, exist_ok=True)
|
||||
|
||||
# 核心:使用 io.BytesIO 直接在内存中读取 zip 内容并解压
|
||||
try:
|
||||
with zipfile.ZipFile(io.BytesIO(response.content)) as zip_ref:
|
||||
zip_ref.extractall(output_folder)
|
||||
print(f"✅ 成功!已解压并保存至文件夹: {output_folder}")
|
||||
except zipfile.BadZipFile:
|
||||
print(f"❌ 失败!{filename} 返回的内容不是有效的 ZIP 格式。")
|
||||
else:
|
||||
print(f"❌ 失败!{filename} 状态码: {response.status_code}, 报错: {response.text}")
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"❌ 网络请求异常 ({filename}): {e}")
|
||||
except Exception as e:
|
||||
print(f"❌ 处理 {filename} 时发生未知错误: {e}")
|
||||
|
||||
print("-" * 30)
|
||||
if args.sync:
|
||||
print("转换任务结束,开始进行文件夹同步清理...")
|
||||
|
||||
# ==========================================
|
||||
# 【新增逻辑】:反向比对,清理多余的 MD 文件夹
|
||||
# ==========================================
|
||||
# 1. 收集当前 ORI_PDF 中所有有效的 PDF 名字(不含后缀)
|
||||
valid_pdf_names = set()
|
||||
for filename in os.listdir(source_dir):
|
||||
if filename.lower().endswith(".pdf"):
|
||||
valid_pdf_names.add(os.path.splitext(filename)[0])
|
||||
|
||||
# 2. 遍历 ORI_MD 文件夹
|
||||
if os.path.exists(target_dir):
|
||||
for folder_name in os.listdir(target_dir):
|
||||
folder_path = os.path.join(target_dir, folder_name)
|
||||
|
||||
# 仅处理文件夹(以防里面有意外的独立文件)
|
||||
if os.path.isdir(folder_path):
|
||||
# 3. 如果这个文件夹的名字不在有效的 PDF 列表中,说明是被删掉的“孤儿”
|
||||
if folder_name not in valid_pdf_names:
|
||||
print(f"🧹 发现多余文件,正在清理: {folder_name}")
|
||||
try:
|
||||
# 使用 shutil.rmtree 删除整个文件夹及其内部所有内容
|
||||
shutil.rmtree(folder_path)
|
||||
except Exception as e:
|
||||
print(f"❌ 删除 {folder_name} 时发生错误: {e}")
|
||||
else:
|
||||
print("转换任务结束,未开启同步清理。")
|
||||
|
||||
print("-" * 30)
|
||||
print("所有批量任务彻底完成!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
print("\n检测到用户中断,程序退出。")
|
||||
Reference in New Issue
Block a user