【问题标题】:How to parse .ttl files with RDFLib?如何使用 RDFLib 解析 .ttl 文件?
【发布时间】:2013-02-16 18:49:58
【问题描述】:

我有一个.ttl 格式的文件。它有 4 个属性/列,其中包含以下形式的四元组:

  1. (id, student_name, student_address, student_phoneno)
  2. (id, faculty_name, faculty_address, faculty_phoneno)

我知道如何使用 RDFLib 解析 .n3 表单三元组;

from rdflib import Graph
g = Graph()
g.parse("demo.nt", format="nt")

但我不确定如何解析这些四元组。

我的目的是解析和提取与特定 id 相关的所有信息。学生和教师的 id 可以相同。

如何使用 RDFLib 处理这些四元组并将其用于基于 id 的聚合?

来自.ttl 文件的示例 sn-p:

#@ <id1>
<Alice> <USA> <12345>

#@ <id1>
<Jane> <France> <78900>

【问题讨论】:

  • 问题中引用的ttl与标签引用的相同吗?
  • @Abhijit 是的,你是对的。 Turtle-Terse RDF 三重语言
  • @KeiraShaw 为什么不只是正则表达式?
  • @SnakesandCoffee 谢谢,但我不明白如何使用正则表达式。 Id 的 id 格式为“#@”。我是 python 新手。你能解释一下吗?感谢您的回复。

标签: python python-2.7 parsing turtle-rdf


【解决方案1】:

目前似乎没有这样的库来解析Turtle - Terse RDF Triple Language

由于您已经知道语法,最好的办法是使用PyParsing 首先创建语法,然后解析文件。

我还建议根据您的需要调整以下EBNF implementation

【讨论】:

    【解决方案2】:

    您可以按照 Snakes 和 Coffee 的建议进行操作,只需将该函数(或其代码)包装在带有 yield 语句的循环中。这将创建一个生成器,可以迭代地调用它来动态创建下一行的字典。假设您要将这些写入 csv,例如,使用 Snakes 的 parse_to_dict:

    import re
    import csv
    
    writer = csv.DictWriter(open(outfile, "wb"), fieldnames=["id", "name", "address", "phone"])
    # or whatever
    

    您可以将生成器创建为函数或内联理解:

    def dict_generator(lines): 
        for line in lines: 
            yield parse_to_dict(line)
    

    --或--

    dict_generator = (parse_to_dict(line) for line in lines)
    

    这些几乎是等价的。此时,您可以通过调用dict_generator.next() 获得一个字典解析的行,并且您会神奇地一次获得一个 - 不涉及额外的 RAM 抖动。

    如果您有 16 gigs 的原始数据,您也可以考虑制作一个生成器来提取线路。它们真的很有用。

    来自 SO 和一些文档的生成器的更多信息: What can you use Python generator functions for? http://wiki.python.org/moin/Generators

    【讨论】:

    • Snakes and coffee..parse_to_dict 行不存在,我忘记了该行打算做什么
    【解决方案3】:

    TurtleNotation 3 语法的子集,因此rdflib 应该能够使用format='n3' 对其进行解析。 检查 rdflib 是否保留 cmets(ids 在您的示例中的 cmets (#...) 中指定)。如果不是,并且输入格式如您的示例中所示简单,那么您可以手动解析它:

    import re
    from collections import namedtuple
    from itertools import takewhile
    
    Entry = namedtuple('Entry', 'id name address phone')
    
    def get_entries(path):
        with open(path) as file:
            # an entry starts with `#@` line and ends with a blank line
            for line in file:
                if line.startswith('#@'):
                    buf = [line]
                    buf.extend(takewhile(str.strip, file)) # read until blank line
                    yield Entry(*re.findall(r'<([^>]+)>', ''.join(buf)))
    
    print("\n".join(map(str, get_entries('example.ttl'))))
    

    输出:

    Entry(id='id1', name='Alice', address='USA', phone='12345')
    Entry(id='id1', name='Jane', address='France', phone='78900')
    

    将条目保存到数据库:

    import sqlite3
    
    with sqlite3.connect('example.db') as conn:
        conn.execute('''CREATE TABLE IF NOT EXISTS entries
                 (id text, name text, address text, phone text)''')
        conn.executemany('INSERT INTO entries VALUES (?,?,?,?)',
                         get_entries('example.ttl'))
    

    如果您需要在 Python 中进行一些后处理,按 id 分组:

    import sqlite3
    from itertools import groupby
    from operator import itemgetter
    
    with sqlite3.connect('example.db') as c:
        rows = c.execute('SELECT * FROM entries ORDER BY id LIMIT ?', (10,))
        for id, group in groupby(rows, key=itemgetter(0)):
            print("%s:\n\t%s" % (id, "\n\t".join(map(str, group))))
    

    输出:

    id1:
        ('id1', 'Alice', 'USA', '12345')
        ('id1', 'Jane', 'France', '78900')
    

    【讨论】:

      【解决方案4】:

      似乎至少从 rdflib 5.0.0 开始支持 turtle。我做了

      from rdflib import Graph
      graph = Graph()
      graph.parse('myfile.ttl', format='ttl')
      

      这解析得很好。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-30
        • 1970-01-01
        • 2022-09-26
        • 1970-01-01
        相关资源
        最近更新 更多