匹配TSV文件ID的Markdown内容提取及TSV数据补全技术求助
问题描述
我有一个由CSV转换而来的TSV文件,以及一个存放Markdown文件的文件夹。需求是:遍历目录中的文件,打开文件名(如File_ID_1)与TSV文件ID列值匹配的Markdown文件,从中提取Animal和Fruit相关内容,分别补充到TSV文件的对应列中。
示例文件
TSV文件(example.tsv)内容:
ID Data Animal Fruit 1 August 2 July 3 May ...
目录Desktop/Files中的文件名:
File_ID_1 File_ID_2 File_ID_3 ...
Markdown文件示例:
File_ID_1 **Animal**: Cat **Fruit**: Peach ...
已完成代码
## Extracting relevant contents from a matched md file import csv import os import re df = 'example.tsv' directory = 'Desktop/Files' id_to_row = {} with open(df, 'r', newline='', encoding='utf-8') as tsv_file: tsv_reader = csv.DictReader(tsv_file, delimiter='\t') for row_idx, row in enumerate(tsv_reader): id_to_row[int(row['ID'])] = row_idx # Process markdown files for filename in os.listdir(directory): if filename.endswith('.md'): id_match = re.match(r'File_ID_(\d+)\.md', filename) if id_match: file_id = int(id_match.group(1)) markdown_path = os.path.join(directory, filename) with open(markdown_path, 'r', encoding='utf-8') as md_file: content = md_file.read()
同事建议用XPath表达式提取内容,但作为编程新手,不知道如何整合所有代码,需要帮助。
解决方案
针对当前的Markdown格式,用正则表达式比XPath更直接高效——XPath需要先把Markdown转成HTML,反而增加复杂度。下面是补全并优化后的完整代码:
import csv import os import re # 配置文件路径 tsv_path = 'example.tsv' md_directory = 'Desktop/Files' # 1. 读取TSV所有数据,保存为列表方便后续修改,同时建立ID到行索引的映射 rows = [] id_to_index = {} with open(tsv_path, 'r', newline='', encoding='utf-8') as tsv_file: reader = csv.DictReader(tsv_file, delimiter='\t') fieldnames = reader.fieldnames # 保存表头 for idx, row in enumerate(reader): row_id = int(row['ID']) rows.append(row) id_to_index[row_id] = idx # 2. 定义正则表达式,匹配Animal和Fruit的内容(忽略大小写) animal_pattern = re.compile(r'\*\*Animal\*\*:\s*(.+)', re.IGNORECASE) fruit_pattern = re.compile(r'\*\*Fruit\*\*:\s*(.+)', re.IGNORECASE) # 3. 遍历Markdown文件,提取内容并更新TSV数据 for filename in os.listdir(md_directory): if not filename.endswith('.md'): continue # 匹配文件名中的ID id_match = re.match(r'File_ID_(\d+)\.md', filename) if not id_match: continue file_id = int(id_match.group(1)) # 检查该ID是否存在于TSV中 if file_id not in id_to_index: print(f"ID {file_id} 未在TSV中找到,跳过文件 {filename}") continue # 读取Markdown文件内容 md_path = os.path.join(md_directory, filename) with open(md_path, 'r', encoding='utf-8') as md_file: content = md_file.read() # 提取并填充Animal字段 animal_match = animal_pattern.search(content) if animal_match: rows[id_to_index[file_id]]['Animal'] = animal_match.group(1).strip() # 提取并填充Fruit字段 fruit_match = fruit_pattern.search(content) if fruit_match: rows[id_to_index[file_id]]['Fruit'] = fruit_match.group(1).strip() # 4. 将更新后的数据写回TSV文件(建议先备份原文件) with open(tsv_path, 'w', newline='', encoding='utf-8') as tsv_file: writer = csv.DictWriter(tsv_file, fieldnames=fieldnames, delimiter='\t') writer.writeheader() writer.writerows(rows) print("TSV文件更新完成")
关键说明
- 为什么不用XPath:XPath是XML/HTML解析工具,处理Markdown需先转成HTML(额外依赖
markdown库),步骤繁琐。当前Markdown格式固定,正则完全能精准匹配。 - 代码优化点:
- 把TSV数据存在列表中,直接修改对应行字段,逻辑更直观。
- 增加ID不存在的判断,避免报错。
- 用
re.IGNORECASE兼容大小写不同的写法(比如**animal**也能识别)。
如果坚持要用XPath,可参考以下简化实现(需额外安装markdown和lxml库):
# 先安装依赖:pip install markdown lxml import markdown from lxml import etree # 读取Markdown内容后转成HTML html_content = markdown.markdown(content) tree = etree.HTML(html_content) # 用XPath提取内容 animal = tree.xpath('//strong[text()="Animal"]/following-sibling::text()') if animal: rows[id_to_index[file_id]]['Animal'] = animal[0].strip().replace(':', '').strip() fruit = tree.xpath('//strong[text()="Fruit"]/following-sibling::text()') if fruit: rows[id_to_index[file_id]]['Fruit'] = fruit[0].strip().replace(':', '').strip()
内容的提问来源于stack exchange,提问作者aoooooiiiiiiiiiiiiiii
相关产品推荐
相关产品推荐

