如何使用Python打开并解析大型N-Triple文件(解决RDFLib解析报错)
RDFLib解析Yago4 N-Triple文件报错解决方法
报错核心原因
- Yago4官方放出的部分N-Triple文件在Win环境下下载后会自带UTF-8 BOM头,RDFLib默认的
nt格式解析器无法识别BOM头,直接触发解析错误 - 大体积知识库文件普遍存在极个别不符合严格N-Triple语法的脏行,默认全量解析模式遇到单条坏行就会直接终止抛出错误
- 直接全量加载G级以上的NT文件内存占用过高,也可能触发非语法类的解析异常
可行方案
方案1:逐行容错解析(推荐,无需额外工具)
不要直接调用g.parse()加载整个文件,改用逐行读取+错误跳过的逻辑,自动处理BOM编码问题,同时跳过坏行不影响整体数据提取:
from rdflib.graph import Graph from rdflib.plugins.parsers.ntriples import ParseError g = Graph() # utf-8-sig编码会自动识别并跳过文件开头的BOM头 with open("yago_data.nt", "r", encoding="utf-8-sig") as f: for line_num, line in enumerate(f, 1): line = line.strip() if not line: continue try: g.parse(data=line, format="nt") except ParseError: # 不需要定位坏行可以直接注释下一行打印逻辑 print(f"跳过第{line_num}行异常内容: {line[:80]}...") continue
如果只是要提取人名列表,不需要把整个知识库加载到内存占资源,可以直接逐行匹配人名相关属性,直接输出到txt文件,处理速度比全量加载到Graph快10倍以上:
import re # 按需调整你需要匹配的人名称谓规则,对应Yago4里的name/label类属性 NAME_PREDICATES = { "<http://www.w3.org/2000/01/rdf-schema#label>", "<http://schema.org/name>", "<http://yago-knowledge.org/prop/hasGivenName>", "<http://yago-knowledge.org/prop/hasFamilyName>" } name_result = set() with open("yago_data.nt", "r", encoding="utf-8-sig") as f: for line in f: line = line.strip() if not line or not line.endswith("."): continue split_parts = line.split(" ", 2) if len(split_parts) < 3: continue subj, pred, obj_part = split_parts if pred in NAME_PREDICATES: # 提取字面量里的人名文本,自动过滤语言标记、数据类型标记 match_res = re.match(r'^"(.+?)"(@[a-z]{2})?(\^\^<.*>)?\.$', obj_part) if match_res: person_name = match_res.group(1) # 可在这里加规则过滤非人名、非目标语言的内容 name_result.add(person_name) # 直接写入纯文本文件 with open("yago_person_names.txt", "w", encoding="utf-8") as out_f: for name in name_result: out_f.write(f"{name}\n")
方案2:格式转换
如果需要把NT文件转成XML、Turtle等其他RDF格式,可以在本地安装RDF处理工具集后用命令行直接转换,工具自带编码兼容和容错能力,对大文件支持更好:
- 转Turtle格式:执行命令
riot --out=turtle yago_data.nt > yago_data.ttl - 转RDF/XML格式:执行命令
riot --out=rdfxml yago_data.nt > yago_data.xml
注意事项
- Win10下不要用系统自带记事本打开编辑GB级以上的NT文件,会自动修改文件编码导致更多解析错误
- 如果报错固定出现在文件第1行,直接用二进制编辑工具删掉文件开头3个字节的BOM标记(
\xef\xbb\xbf)即可正常用默认方法解析 - 提取人名时建议优先过滤带
@en、@zh等明确语言标记的字面量,减少无关数据混入
内容的提问来源于stack exchange,提问作者joey11235
相关产品推荐
相关产品推荐

