Как анализировать файлы .ttl с помощью RDFLib?

У меня есть файл в .ttl форме. Он имеет 4 атрибута / столбца, содержащих четверки следующего вида:

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

Я знаю, как разбирать .n3 тройки с помощью RDFLib;

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

но я не уверен, как разбирать эти четверки.

Моя цель - проанализировать и извлечь всю информацию, относящуюся к определенному идентификатору. Идентификатор может быть одинаковым как для студента, так и для преподавателя.

Как я могу использовать RDFLib для обработки этих четверок и использовать ее для агрегирования на основе id?

Пример фрагмента из .ttl файла:

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

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

person Keira Shaw    schedule 02.03.2013    source источник
comment
Совпадает ли ttl в вопросе с тем, на который ссылается тег?   -  person Snakes and Coffee    schedule 02.03.2013
comment
Я думаю, это Turtle - Terse RDF Triple Language   -  person Abhijit    schedule 02.03.2013
comment
@Abhijit Да, вы правы. Черепахово-краткий тройной язык RDF   -  person Keira Shaw    schedule 02.03.2013
comment
@KeiraShaw, почему не просто регулярное выражение?   -  person Snakes and Coffee    schedule 02.03.2013
comment
@SnakesandCoffee Спасибо, но я не понимаю, как я могу использовать на нем регулярное выражение. Идентификатор формы # @ ‹id1›. Я новичок в питоне. Не могли бы вы объяснить. Спасибо за ответ.   -  person Keira Shaw    schedule 02.03.2013


Ответы (4)


Turtle - это подмножество синтаксиса Notation 3, поэтому rdflib должен иметь возможность анализировать его с помощью format='n3'. Проверьте, сохраняет ли rdflib комментарии (id указаны в комментариях (#...) в вашем примере). Если нет, и формат ввода такой же простой, как показано в вашем примере, вы можете проанализировать его вручную:

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:

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')
person jfs    schedule 02.03.2013

Похоже, turtle поддерживается как минимум в rdflib 5.0.0. я сделал

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

Это просто отлично разбирается.

person labyrinth    schedule 10.07.2021

Вы можете сделать так, как предлагают Snakes and Coffee, только заключить эту функцию (или ее код) в цикл с операторами yield. Это создает генератор, который можно вызывать итеративно для создания словарных сообщений следующей строки на лету. Предположим, вы собираетесь записать их в csv, например, используя 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)

--or--

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

Они в значительной степени эквивалентны. На этом этапе вы можете получить строку, проанализированную с помощью dict, вызвав dict_generator.next(), и вы волшебным образом получите по одной за раз - без дополнительной перегрузки ОЗУ.

Если у вас есть 16 гигабайт необработанных данных, вы также можете подумать о создании генератора, который будет вставлять строки. Они действительно полезны.

Дополнительная информация о генераторах от SO и некоторые документы: Что можно использовать с генератором Python функции для? http://wiki.python.org/moin/Generators

person a p    schedule 02.03.2013
comment
Змеи и кофе ... строки parse_to_dict нет, и я забыл, что эта строка намеревалась делать - person Keira Shaw; 02.03.2013

Кажется, в настоящее время нет такой библиотеки для анализа Turtle - Terse RDF Triple Language

Поскольку вы уже знаете грамматику, лучше всего использовать PyParsing, чтобы сначала создать грамматику, а затем проанализировать файл. .

Я также предлагаю адаптировать следующую реализацию EBNF для ваших нужд

person Abhijit    schedule 02.03.2013