Compare commits
4 Commits
e12f34ed5d
...
998d4dbd27
| Author | SHA1 | Date | |
|---|---|---|---|
| 998d4dbd27 | |||
| 9d643187ae | |||
| 2273f62843 | |||
| 40d7953e3a |
@@ -15,7 +15,6 @@ from datetime import datetime
|
|||||||
import time
|
import time
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import shutil
|
|
||||||
|
|
||||||
|
|
||||||
def clear_directory(dir_path: Path) -> None:
|
def clear_directory(dir_path: Path) -> None:
|
||||||
@@ -137,18 +136,44 @@ def read_docx_content(doc_path: Path) -> List[str]:
|
|||||||
has_tab_in_first_rows = any('\t' in line for line in lines[:6])
|
has_tab_in_first_rows = any('\t' in line for line in lines[:6])
|
||||||
|
|
||||||
if not has_tab_in_first_rows and len(lines) >= 6:
|
if not has_tab_in_first_rows and len(lines) >= 6:
|
||||||
# 可能是每行一个字段,尝试合并为 6 段
|
# 判断是否是 6 行一组的模式:第二行是网址且第三行是日期/时间
|
||||||
|
def is_url_line(line: str) -> bool:
|
||||||
|
"""判断一行是否是网址"""
|
||||||
|
return bool(re.match(r'^https?://', line.strip()))
|
||||||
|
|
||||||
|
def is_datetime_line(line: str) -> bool:
|
||||||
|
"""判断一行是否是日期或时间"""
|
||||||
|
datetime_pattern = r'^\d{4}[-/]\d{1,2}[-/]\d{1,2}\s+\d{1,2}:\d{2}'
|
||||||
|
date_pattern = r'^\d{4}[-/]\d{1,2}[-/]\d{1,2}'
|
||||||
|
return bool(re.match(datetime_pattern, line.strip())) or \
|
||||||
|
bool(re.match(date_pattern, line.strip()))
|
||||||
|
|
||||||
|
# 检查当前起始位置是否是 6 行一组模式
|
||||||
|
def is_six_row_group(lines: list, start_idx: int) -> bool:
|
||||||
|
"""检查从 start_idx 开始是否是 6 行一组"""
|
||||||
|
if start_idx + 1 < len(lines):
|
||||||
|
return is_url_line(lines[start_idx + 1]) and \
|
||||||
|
is_datetime_line(lines[start_idx + 2])
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 按组处理,每组独立判断 offset
|
||||||
|
# 规则:如果第二行是网址且第三行是日期/时间,则当前 6 行为一组;否则丢弃第一行,继续判断
|
||||||
result = []
|
result = []
|
||||||
i = 0
|
i = 0
|
||||||
while i < len(lines):
|
while i + 5 <= len(lines):
|
||||||
if i + 5 <= len(lines):
|
# 检查当前位置开始是否是 6 行一组模式
|
||||||
# 尝试合并接下来的 6 行作为一段
|
if is_six_row_group(lines, i):
|
||||||
|
# 是 6 行一组,合并这 6 行
|
||||||
combined = '\t'.join(lines[i:i+6])
|
combined = '\t'.join(lines[i:i+6])
|
||||||
result.append(combined)
|
result.append(combined)
|
||||||
i += 6
|
i += 6
|
||||||
else:
|
else:
|
||||||
result.append(lines[i])
|
# 不是 6 行一组,丢弃当前行(相当于 offset+1)
|
||||||
i += 1
|
i += 1
|
||||||
|
# 处理剩余行(不足 6 行的)
|
||||||
|
while i < len(lines):
|
||||||
|
result.append(lines[i])
|
||||||
|
i += 1
|
||||||
return result
|
return result
|
||||||
else:
|
else:
|
||||||
# 每行已经有\t分割,直接返回
|
# 每行已经有\t分割,直接返回
|
||||||
@@ -423,74 +448,40 @@ def main():
|
|||||||
extract_all_zips(source_dir, "data", delete_original=args.delete_original)
|
extract_all_zips(source_dir, "data", delete_original=args.delete_original)
|
||||||
return
|
return
|
||||||
|
|
||||||
# 批量处理所有 zip 文件
|
# 批量处理所有文件夹(已从 cc 目录解压好)
|
||||||
if True or args.batch:
|
if True or args.batch:
|
||||||
source_dir = Path(args.base_dir) if args.base_dir else Path("cc")
|
source_dir = Path(args.base_dir) if args.base_dir else Path("cc")
|
||||||
data_dir = Path("data")
|
data_dir = Path("data")
|
||||||
server_jsons_dir = Path("server") / "jsons"
|
server_jsons_dir = Path("server") / "jsons"
|
||||||
server_jsons_dir.mkdir(parents=True, exist_ok=True)
|
server_jsons_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
zip_files = list(source_dir.glob("*.zip"))
|
# 获取 cc 目录下的所有子文件夹(已解压好的文件夹)
|
||||||
|
folders = [f for f in source_dir.iterdir() if f.is_dir()]
|
||||||
|
|
||||||
if not zip_files:
|
if not folders:
|
||||||
print(f"在 {source_dir} 中未发现 zip 文件")
|
print(f"在 {source_dir} 中未发现文件夹")
|
||||||
return
|
return
|
||||||
|
|
||||||
# 清空 data 目录
|
print(f"找到 {len(folders)} 个文件夹,开始批量处理...")
|
||||||
clear_directory(data_dir)
|
|
||||||
|
|
||||||
print(f"找到 {len(zip_files)} 个压缩文件,开始批量处理...")
|
|
||||||
success_count = 0
|
success_count = 0
|
||||||
fail_count = 0
|
fail_count = 0
|
||||||
|
|
||||||
for zip_file in zip_files:
|
for folder in folders:
|
||||||
print(f"\n【开始处理】{zip_file.name}")
|
print(f"\n【开始处理】{folder.name}")
|
||||||
|
# 清空 data 目录
|
||||||
# 清空当前 zip 文件的提取目录
|
clear_directory(data_dir)
|
||||||
extract_dir = data_dir / zip_file.stem
|
|
||||||
if extract_dir.exists():
|
|
||||||
clear_directory(extract_dir)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 先提取所有文件
|
# 移动文件夹到 data 目录
|
||||||
with zipfile.ZipFile(zip_file, 'r') as zip_ref:
|
extract_dir = data_dir / folder.name
|
||||||
zip_ref.extractall(data_dir)
|
shutil.move(str(folder), str(extract_dir))
|
||||||
|
# 更新 folder 变量,避免后续移动时路径不正确
|
||||||
# 然后遍历所有成员,设置时间戳
|
folder = extract_dir
|
||||||
with zipfile.ZipFile(zip_file, 'r') as zip_ref:
|
|
||||||
for member in zip_ref.infolist():
|
|
||||||
# 构建正确的文件路径 - 先获取解压后的实际路径
|
|
||||||
base_extract_path = data_dir / zip_file.stem
|
|
||||||
if member.filename.startswith(zip_file.stem + '/'):
|
|
||||||
# 文件路径包含 zip 文件名前缀
|
|
||||||
member_path = base_extract_path / member.filename[len(zip_file.stem) + 1:]
|
|
||||||
elif member.filename.startswith(zip_file.stem):
|
|
||||||
# 文件路径直接以 zip 文件名开头
|
|
||||||
member_path = base_extract_path / member.filename[len(zip_file.stem):].lstrip('/')
|
|
||||||
else:
|
|
||||||
# 文件路径不包含前缀
|
|
||||||
member_path = base_extract_path / member.filename
|
|
||||||
|
|
||||||
# 如果路径存在,设置时间戳
|
|
||||||
if member_path.exists():
|
|
||||||
try:
|
|
||||||
date_time = datetime(*member.date_time[:5])
|
|
||||||
timestamp = date_time.timestamp()
|
|
||||||
os.utime(member_path, (timestamp, timestamp))
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# 检查是否多了一层目录
|
|
||||||
inner_dir = extract_dir / zip_file.stem
|
|
||||||
if inner_dir.is_dir() and len(list(extract_dir.iterdir())) == 1:
|
|
||||||
for item in inner_dir.iterdir():
|
|
||||||
item.rename(extract_dir / item.name)
|
|
||||||
inner_dir.rmdir()
|
|
||||||
|
|
||||||
# 查找 Word 文档
|
# 查找 Word 文档
|
||||||
word_doc = find_word_doc_recursive(extract_dir)
|
word_doc = find_word_doc_recursive(extract_dir)
|
||||||
if not word_doc:
|
if not word_doc:
|
||||||
print(f"⚠️ 在 {zip_file.name} 中未找到 Word 文档")
|
print(f"⚠️ 在 {folder.name} 中未找到 Word 文档")
|
||||||
fail_count += 1
|
fail_count += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -509,8 +500,31 @@ def main():
|
|||||||
twole_folder = base_dir / "21世纪教育网"
|
twole_folder = base_dir / "21世纪教育网"
|
||||||
zxxk_folder = base_dir / "学科网"
|
zxxk_folder = base_dir / "学科网"
|
||||||
|
|
||||||
if not twole_folder.exists() or not zxxk_folder.exists():
|
if not zxxk_folder.exists():
|
||||||
print("❌ 文件夹不存在,请先解压文件")
|
print("❌ 文件夹不存在,请先解压文件")
|
||||||
|
# 将失败的文件移动到本程序所在目录的 ee 子目录
|
||||||
|
script_dir = Path(__file__).parent
|
||||||
|
ee_dir = script_dir / "ee"
|
||||||
|
ee_dir.mkdir(exist_ok=True)
|
||||||
|
dest_file = ee_dir / folder.name
|
||||||
|
shutil.move(str(folder), str(dest_file))
|
||||||
|
print(f" 已移动失败文件到:{dest_file}")
|
||||||
|
fail_count += 1
|
||||||
|
continue
|
||||||
|
if not twole_folder.exists():
|
||||||
|
twole_folder = base_dir / "二一教育"
|
||||||
|
if not twole_folder.exists():
|
||||||
|
twole_folder = base_dir / "21世纪教育"
|
||||||
|
if not twole_folder.exists():
|
||||||
|
print("❌ 文件夹不存在,请先解压文件")
|
||||||
|
# 将失败的文件移动到本程序所在目录的 ee 子目录
|
||||||
|
script_dir = Path(__file__).parent
|
||||||
|
ee_dir = script_dir / "ee"
|
||||||
|
ee_dir.mkdir(exist_ok=True)
|
||||||
|
dest_file = ee_dir
|
||||||
|
print(str(folder), str(dest_file))
|
||||||
|
shutil.move(str(folder), str(dest_file))
|
||||||
|
print(f" 已移动失败文件到:{dest_file}")
|
||||||
fail_count += 1
|
fail_count += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -523,9 +537,9 @@ def main():
|
|||||||
|
|
||||||
print(f"✓ JSON 文件已保存到:{output_file}")
|
print(f"✓ JSON 文件已保存到:{output_file}")
|
||||||
|
|
||||||
# 删除原压缩包
|
# 删除原文件夹
|
||||||
if args.delete_original:
|
if args.delete_original:
|
||||||
zip_file.unlink()
|
shutil.rmtree(folder)
|
||||||
|
|
||||||
success_count += 1
|
success_count += 1
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user