Как анализировать файлы.ttl с помощью RDFLib?
У меня есть файл в .ttl
форма. Он имеет 4 атрибута / столбца, содержащих четверки следующего вида:
(id, student_name, student_address, student_phoneno)
,(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>
4 ответа
Черепаха является подмножеством Notation 3
синтаксис, поэтому rdflib должен иметь возможность анализировать его с помощью format='n3'
, Проверьте, rdflib
сохраняет комментарии (id
s указаны в комментариях (#...
) в вашем образце). Если нет, и формат ввода такой же простой, как показано в вашем примере, вы можете разобрать его вручную:
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')
Похоже, turtle поддерживается по крайней мере с rdflib 5.0.0. я сделал
from rdflib import Graph
graph = Graph()
graph.parse('myfile.ttl', format='ttl')
Это просто отлично разбирается.
Вы можете делать то, что предлагает Snakes and Coffee, только обернуть эту функцию (или ее код) в цикл с операторами yield. Это создает генератор, который можно вызывать итеративно, чтобы создавать на следующей строке дикты на лету. Предполагая, что вы собираетесь записать их в CSV, например, используя Snake ' 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()
, и вы волшебным образом получите по одному за раз, без дополнительной перегрузки ОЗУ.
Если у вас есть 16 гигабайт необработанных данных, вы можете подумать и о создании генератора, в котором можно было бы использовать и линии. Они действительно полезны.
Больше информации о генераторах из SO и некоторых документах: Для чего вы можете использовать функции генератора Python? http://wiki.python.org/moin/Generators
Похоже, в настоящее время нет такой библиотеки для анализа Turtle - Terse RDF Triple Language
Поскольку вы уже знаете грамматику, лучше всего использовать PyParsing, чтобы сначала создать грамматику, а затем проанализировать файл.
Я также предложил бы адаптировать следующую реализацию EBNF для ваших нужд