modified pppp
This commit is contained in:
@@ -628,8 +628,27 @@ def has_audio_video_files(files_list: List[Dict]) -> bool:
|
||||
return any(file_entry.get('name', '').lower().endswith(ext) for file_entry in files_list for ext in audio_video_exts)
|
||||
|
||||
|
||||
def create_empty_time_classification_report() -> Dict[str, List[Dict]]:
|
||||
return {
|
||||
"single_files": [],
|
||||
"archives": [],
|
||||
"same_child_archive_time": [],
|
||||
"zxxk_child_earlier": [],
|
||||
"twole_child_earlier": [],
|
||||
}
|
||||
|
||||
|
||||
def merge_time_classification_reports(target: Dict[str, List[Dict]], source: Dict[str, List[Dict]]) -> None:
|
||||
for category in create_empty_time_classification_report():
|
||||
target.setdefault(category, [])
|
||||
target[category].extend(source.get(category, []))
|
||||
|
||||
|
||||
def build_file_associations(word_content: List[str], twole_folder: Path, zxxk_folder: Path) -> Dict:
|
||||
"""构建文件关联关系"""
|
||||
SAME_TIME_THRESHOLD = 300
|
||||
PAIR_TIME_DIFF_THRESHOLD = 30
|
||||
|
||||
def process_file(file_path: Path) -> List[Dict]:
|
||||
files = []
|
||||
mtime = file_path.stat().st_mtime
|
||||
@@ -657,35 +676,94 @@ def build_file_associations(word_content: List[str], twole_folder: Path, zxxk_fo
|
||||
files.append({"name": f.name, "mtime": mtime, "datetime": format_datetime(mtime), "path": str(f)})
|
||||
return files
|
||||
|
||||
def get_latest_extracted_mtime(file_entries: List[Dict], archive_name: str) -> Optional[float]:
|
||||
def get_archive_time_summary(file_entries: List[Dict], archive_name: str) -> Dict:
|
||||
extracted_times = [e["mtime"] for e in file_entries if e.get("name") != archive_name and "mtime" in e]
|
||||
if not extracted_times:
|
||||
return None
|
||||
archive_mtime = next((e["mtime"] for e in file_entries if e.get("name") == archive_name), None)
|
||||
if not extracted_times:
|
||||
return {
|
||||
"archive_mtime": archive_mtime,
|
||||
"archive_datetime": format_datetime(archive_mtime) if archive_mtime else None,
|
||||
"latest_child_mtime": None,
|
||||
"latest_child_datetime": None,
|
||||
"child_archive_time_relation": "no_child_files",
|
||||
"child_archive_time_diff_seconds": None,
|
||||
}
|
||||
latest_extracted = max(extracted_times)
|
||||
return None if archive_mtime and abs(latest_extracted - archive_mtime) < 300 else latest_extracted
|
||||
time_diff = latest_extracted - archive_mtime if archive_mtime is not None else None
|
||||
is_same_time = time_diff is not None and abs(time_diff) < SAME_TIME_THRESHOLD
|
||||
return {
|
||||
"archive_mtime": archive_mtime,
|
||||
"archive_datetime": format_datetime(archive_mtime) if archive_mtime else None,
|
||||
"latest_child_mtime": latest_extracted,
|
||||
"latest_child_datetime": format_datetime(latest_extracted),
|
||||
"child_archive_time_relation": "same" if is_same_time else "different",
|
||||
"child_archive_time_diff_seconds": time_diff,
|
||||
}
|
||||
|
||||
def match_group(title: str, url: str, time_val: str, group_name: str, twole_files: List, zxxk_files: List) -> Tuple[Dict, Optional[float]]:
|
||||
def build_classification_record(row_index: int, group_name: str, entry: Dict, file_kind: str, archive_summary: Optional[Dict] = None) -> Dict:
|
||||
site = get_url_site(entry.get("url", ""))
|
||||
record = {
|
||||
"row_index": row_index,
|
||||
"group": group_name,
|
||||
"site": site,
|
||||
"site_name": "二一教育" if site == "twole" else "学科网" if site == "zxxk" else "",
|
||||
"file_kind": file_kind,
|
||||
"title": entry.get("title"),
|
||||
"url": entry.get("url"),
|
||||
"time": entry.get("time"),
|
||||
"source_path": entry.get("source_path"),
|
||||
"file": entry.get("files", [{}])[0] if entry.get("files") else {},
|
||||
}
|
||||
if archive_summary:
|
||||
record.update(archive_summary)
|
||||
return record
|
||||
|
||||
def build_pair_record(row_index: int, entry: Dict, twole_summary: Dict, zxxk_summary: Dict, earlier_site: str) -> Dict:
|
||||
twole_entry = twole_summary["entry"]
|
||||
zxxk_entry = zxxk_summary["entry"]
|
||||
return {
|
||||
"row_index": row_index,
|
||||
"earlier_site": "二一教育" if earlier_site == "twole" else "学科网",
|
||||
"earlier_site_key": earlier_site,
|
||||
"twole_latest_child_mtime": twole_summary["archive"]["latest_child_mtime"],
|
||||
"twole_latest_child_datetime": twole_summary["archive"]["latest_child_datetime"],
|
||||
"zxxk_latest_child_mtime": zxxk_summary["archive"]["latest_child_mtime"],
|
||||
"zxxk_latest_child_datetime": zxxk_summary["archive"]["latest_child_datetime"],
|
||||
"child_time_diff_seconds": zxxk_summary["archive"]["latest_child_mtime"] - twole_summary["archive"]["latest_child_mtime"],
|
||||
"twole": twole_entry,
|
||||
"zxxk": zxxk_entry,
|
||||
"group1": entry.get("group1"),
|
||||
"group2": entry.get("group2"),
|
||||
}
|
||||
|
||||
def match_group(title: str, url: str, time_val: str, group_name: str, twole_files: List, zxxk_files: List) -> Tuple[Dict, Dict]:
|
||||
if 'www.21cnjy.com' in url and twole_files:
|
||||
candidates = twole_files
|
||||
elif 'www.zxxk.com' in url and zxxk_files:
|
||||
candidates = zxxk_files
|
||||
else:
|
||||
return {}, None
|
||||
return {}, {}
|
||||
|
||||
best_match = find_best_match(title, candidates)
|
||||
if not best_match:
|
||||
return {}, None
|
||||
return {}, {}
|
||||
|
||||
candidates.remove(best_match)
|
||||
file_path, _ = best_match
|
||||
files = process_file(file_path)
|
||||
entry = {"files": files, "title": title, "url": url, "time": time_val, "source_path": str(file_path)}
|
||||
latest = get_latest_extracted_mtime(files, file_path.name) if file_path.suffix.lower() in ('.zip', '.rar', '.7z') else None
|
||||
return entry, latest
|
||||
is_archive = file_path.suffix.lower() in ARCHIVE_EXTENSIONS
|
||||
summary = {
|
||||
"entry": entry,
|
||||
"group_name": group_name,
|
||||
"site": get_url_site(url),
|
||||
"is_archive": is_archive,
|
||||
"archive": get_archive_time_summary(files, file_path.name) if is_archive else None,
|
||||
}
|
||||
return entry, summary
|
||||
|
||||
result = []
|
||||
problematic_groups = []
|
||||
problematic_groups = create_empty_time_classification_report()
|
||||
twole_files = get_files_with_times(twole_folder)
|
||||
zxxk_files = get_files_with_times(zxxk_folder)
|
||||
|
||||
@@ -698,8 +776,8 @@ def build_file_associations(word_content: List[str], twole_folder: Path, zxxk_fo
|
||||
title2, url2, time2 = parts[3].strip(), parts[4].strip(), parts[5].strip()
|
||||
|
||||
entry = {}
|
||||
group1_entry, group1_latest = match_group(title1, url1, time1, "group1", twole_files, zxxk_files)
|
||||
group2_entry, group2_latest = match_group(title2, url2, time2, "group2", twole_files, zxxk_files)
|
||||
group1_entry, group1_summary = match_group(title1, url1, time1, "group1", twole_files, zxxk_files)
|
||||
group2_entry, group2_summary = match_group(title2, url2, time2, "group2", twole_files, zxxk_files)
|
||||
|
||||
if group1_entry:
|
||||
entry["group1"] = group1_entry
|
||||
@@ -707,13 +785,44 @@ def build_file_associations(word_content: List[str], twole_folder: Path, zxxk_fo
|
||||
entry["group2"] = group2_entry
|
||||
|
||||
if entry:
|
||||
pair_sites = {get_url_site(entry.get("group1", {}).get("url", "")), get_url_site(entry.get("group2", {}).get("url", ""))}
|
||||
if (pair_sites == {'twole', 'zxxk'} and group1_latest is not None and group2_latest is not None and
|
||||
group1_latest < group2_latest and (group2_latest - group1_latest) > 30):
|
||||
problematic_groups.append({
|
||||
"row_index": i, "group1_latest_extracted_mtime": group1_latest, "group2_latest_extracted_mtime": group2_latest,
|
||||
"group1": entry.get("group1"), "group2": entry.get("group2")
|
||||
})
|
||||
archive_summaries_by_site = {}
|
||||
for summary in (group1_summary, group2_summary):
|
||||
if not summary:
|
||||
continue
|
||||
record = build_classification_record(
|
||||
i,
|
||||
summary["group_name"],
|
||||
summary["entry"],
|
||||
"archive" if summary["is_archive"] else "single_file",
|
||||
summary["archive"],
|
||||
)
|
||||
if summary["is_archive"]:
|
||||
problematic_groups["archives"].append(record)
|
||||
archive_summaries_by_site[summary["site"]] = summary
|
||||
if summary["archive"]["child_archive_time_relation"] == "same":
|
||||
problematic_groups["same_child_archive_time"].append(record)
|
||||
else:
|
||||
problematic_groups["single_files"].append(record)
|
||||
|
||||
twole_summary = archive_summaries_by_site.get("twole")
|
||||
zxxk_summary = archive_summaries_by_site.get("zxxk")
|
||||
if twole_summary and zxxk_summary:
|
||||
twole_archive = twole_summary["archive"]
|
||||
zxxk_archive = zxxk_summary["archive"]
|
||||
if (twole_archive["child_archive_time_relation"] == "different" and
|
||||
zxxk_archive["child_archive_time_relation"] == "different" and
|
||||
twole_archive["latest_child_mtime"] is not None and
|
||||
zxxk_archive["latest_child_mtime"] is not None):
|
||||
child_time_diff = zxxk_archive["latest_child_mtime"] - twole_archive["latest_child_mtime"]
|
||||
if abs(child_time_diff) > PAIR_TIME_DIFF_THRESHOLD:
|
||||
if child_time_diff < 0:
|
||||
problematic_groups["zxxk_child_earlier"].append(
|
||||
build_pair_record(i, entry, twole_summary, zxxk_summary, "zxxk")
|
||||
)
|
||||
else:
|
||||
problematic_groups["twole_child_earlier"].append(
|
||||
build_pair_record(i, entry, twole_summary, zxxk_summary, "twole")
|
||||
)
|
||||
result.append(entry)
|
||||
|
||||
return {"items": result, "problematic_groups": problematic_groups}
|
||||
@@ -929,7 +1038,7 @@ def main():
|
||||
total_failures = 0
|
||||
total_conflicts = 0
|
||||
total_duplicates = 0
|
||||
all_problem_groups = []
|
||||
all_problem_groups = create_empty_time_classification_report()
|
||||
all_write_reports = []
|
||||
|
||||
for source_item in source_items:
|
||||
@@ -964,10 +1073,12 @@ def main():
|
||||
print(f" 关联目录:{base_dir}")
|
||||
|
||||
associations = build_file_associations(word_content, twole_folder, zxxk_folder)
|
||||
for group in associations.get("problematic_groups", []):
|
||||
group["source_folder"] = source_item.name
|
||||
group["word_doc"] = word_doc.name
|
||||
all_problem_groups.extend(associations.get("problematic_groups", []))
|
||||
classification_report = associations.get("problematic_groups", create_empty_time_classification_report())
|
||||
for records in classification_report.values():
|
||||
for record in records:
|
||||
record["source_folder"] = source_item.name
|
||||
record["word_doc"] = word_doc.name
|
||||
merge_time_classification_reports(all_problem_groups, classification_report)
|
||||
|
||||
if not associations.get("items"):
|
||||
print("⚠️ 未构建出有效关联")
|
||||
|
||||
Reference in New Issue
Block a user