diff --git a/match_all.py b/match_all.py deleted file mode 100644 index e63a20d..0000000 --- a/match_all.py +++ /dev/null @@ -1,145 +0,0 @@ -#!/usr/bin/env python3 -# 遍历 jsons/ 目录下所有 JSON 文件,按 URL 来源匹配 Excel 暗码: -# - url 含 www.21cnjy.com → 在 "21世纪资料名" 列精确匹配 filename[0] -# - url 含 www.zxxk.com → 在 "学科网资料名" 列精确匹配 filename[0] -# 学科网资料名有重复时,从 item 的 url 中提取数字 ID 与各暗码候选值比对消歧 -# - 匹配成功写入 xkw_code,未匹配写入 "0" -# - 未匹配数据汇总写入 问题数据/未匹配填充0.json - -import json # 用于读写 JSON 文件 -import re # 用于正则表达式提取 URL 中的数字 ID -import glob # 用于批量匹配目录下的文件路径 -import openpyxl # 用于读取 Excel (.xlsx) 文件 - -EXCEL_PATH = "结果.xlsx" # Excel 数据文件路径 -JSON_DIR = "jsons" # JSON 文件所在目录 -UNMATCHED_OUT = "问题数据/未匹配填充0.json" # 未匹配数据输出路径 - - -def clean(v): - # 将单元格值转为字符串并去除首尾空格 - if not v: - return "" # 空值直接返回空字符串 - s = str(v).strip() # 转字符串并去首尾空白 - if s.startswith("'"): - s = s[1:] # 去掉 Excel 强制文本时产生的前导单引号(如以 + 开头的单元格) - return s - - -def load_excel_indexes(path): - # 读取 Excel 文件,构建两个查找字典 - # 返回: - # map_21: {21世纪资料名 → 暗码} - # map_xkw: {学科网资料名 → [暗码, ...]} (同名可能对应多个暗码,全部保留) - wb = openpyxl.load_workbook(path) # 打开 Excel 文件 - ws = wb.active # 取活动工作表 - headers = [cell.value for cell in ws[1]] # 读取第一行作为列名 - col = {h: i for i, h in enumerate(headers)} # 构建列名到列索引的映射 - - idx_21 = col["21世纪资料名"] # "21世纪资料名" 列的索引 - idx_xkw = col["学科网资料名"] # "学科网资料名" 列的索引 - idx_code = col["暗码"] # "暗码" 列的索引 - - map_21 = {} # 21世纪资料名 → 暗码(唯一映射,重复则后者覆盖前者) - map_xkw = {} # 学科网资料名 → [暗码列表](同名保留全部暗码) - for row in ws.iter_rows(min_row=2, values_only=True): # 从第2行开始逐行读取 - code = clean(row[idx_code]) # 读取并清洗暗码 - name_21 = clean(row[idx_21]) # 读取并清洗 21世纪资料名 - name_xkw = clean(row[idx_xkw]) # 读取并清洗学科网资料名 - if name_21 and code: - map_21[name_21] = code # 写入 21世纪索引 - if name_xkw and code: - map_xkw.setdefault(name_xkw, []).append(code) # 追加到学科网索引列表 - - return map_21, map_xkw # 返回两个索引字典 - - -def extract_url_id(url): - # 从学科网 URL 中提取纯数字资源 ID - # 例如 https://www.zxxk.com/soft/38079968.html → '38079968' - m = re.search(r'/(\d+)(?:\.\w+)?(?:\?|$)', url) # 匹配路径最后一段的纯数字 - return m.group(1) if m else None # 有匹配则返回数字字符串,否则返回 None - - -def resolve_xkw_code(fn0, url, map_xkw): - # 学科网资料名匹配逻辑: - # - 无匹配 → 返回 None - # - 只有一个唯一暗码 → 直接返回 - # - 多个不同暗码(同名不同资源)→ 用 URL ID 消歧,找到匹配则返回,否则返回 None - codes = map_xkw.get(fn0) # 查找该文件名对应的暗码列表 - if not codes: - return None # 在学科网索引中找不到该文件名 - unique_codes = list(dict.fromkeys(codes)) # 去重并保持原顺序 - if len(unique_codes) == 1: - return unique_codes[0] # 唯一暗码,直接返回 - url_id = extract_url_id(url) # 从 URL 中提取数字 ID - if url_id and url_id in codes: - return url_id # URL ID 与某个暗码一致,用该值 - return None # 无法消歧,返回 None - - -def process_file(json_path, map_21, map_xkw): - # 处理单个 JSON 文件:为每个 item 写入 xkw_code - with open(json_path, encoding="utf-8") as f: - data = json.load(f) # 读取 JSON 数据 - - matched = 0 # 成功匹配的计数 - unmatched_items = [] # 未匹配的 item 列表,用于汇总输出 - - for item in data.get("items", []): # 遍历每个资源 item - fns = item.get("filename", []) # 读取 filename 列表 - if not fns: - continue # filename 为空则跳过该 item - fn0 = fns[0].strip() # 只取第一个 filename 并去空格 - url = item.get("url", "") # 读取该 item 的 URL - - code = None # 初始化暗码为空 - if "www.21cnjy.com" in url: - code = map_21.get(fn0) # 在 21世纪索引中精确查找 - elif "www.zxxk.com" in url: - code = resolve_xkw_code(fn0, url, map_xkw) # 在学科网索引中查找(含消歧) - - if code: - item["xkw_code"] = code # 匹配成功,写入暗码 - matched += 1 # 匹配计数加一 - else: - item["xkw_code"] = "0" # 未匹配,填充 "0" - unmatched_items.append({ - "source_file": json_path, # 来源 JSON 文件路径 - "filename": fn0, # 未匹配的文件名 - "url": url, # 对应的 URL - }) - - with open(json_path, "w", encoding="utf-8") as f: - json.dump(data, f, ensure_ascii=False, indent=2) # 将修改后的数据写回 JSON 文件 - - return matched, unmatched_items # 返回匹配数和未匹配列表 - - -def main(): - print("加载 Excel 索引...") - map_21, map_xkw = load_excel_indexes(EXCEL_PATH) # 构建 Excel 查找索引 - print(f"Excel 索引:21世纪 {len(map_21)} 条,学科网 {len(map_xkw)} 个不重复名称\n") - - files = sorted(glob.glob(f"{JSON_DIR}/*.json")) # 获取所有 JSON 文件路径并排序 - total_files = len(files) # JSON 文件总数 - total_matched = 0 # 全局匹配计数 - all_unmatched = [] # 全局未匹配列表 - - for i, path in enumerate(files, 1): # 逐个处理每个 JSON 文件 - matched, unmatched_items = process_file(path, map_21, map_xkw) # 处理单文件 - total_matched += matched # 累加匹配数 - all_unmatched.extend(unmatched_items) # 合并未匹配列表 - print(f"[{i}/{total_files}] {path} 匹配:{matched} 未匹配:{len(unmatched_items)}") - - with open(UNMATCHED_OUT, "w", encoding="utf-8") as f: - json.dump(all_unmatched, f, ensure_ascii=False, indent=2) # 写出所有未匹配数据 - - total_unmatched = len(all_unmatched) # 全局未匹配总数 - print(f"\n完成:处理 {total_files} 个文件,写入 xkw_code {total_matched + total_unmatched} 条" - f"(匹配:{total_matched},填0:{total_unmatched})") - print(f"未匹配数据已保存至 {UNMATCHED_OUT}") # 提示未匹配数据保存路径 - - -if __name__ == "__main__": - main() # 脚本直接运行时执行 main 函数