知识推理之基于rdflib的RDF文件构建与使用(二)

举报
北纬30度 发表于 2021/07/07 19:43:15 2021/07/07
【摘要】 本文介绍了如何通过rdflib构建RDF文件。

RDFLib初探

RDFLib对RDF文件进行操作的主要接口是Graph。 RDFLib图不是排序容器;它们具有普通的set操作(例如,通过add()方法添加三元组)以及搜索三元组并以任意顺序返回。 RDFLib图重新定义了某些内置Python方法。以下是官方给出的demo。

import rdflib

# create a Graph
g = rdflib.Graph()

# parse in an RDF file hosted on the Internet
result = g.parse("http://www.w3.org/People/Berners-Lee/card")

# loop through each triple in the graph (subj, pred, obj)
for subj, pred, obj in g:
    # check if there is at least one triple in the Graph
    if (subj, pred, obj) not in g:
       raise Exception("It better be!")

# print the number of "triples" in the Graph
print("graph has {} statements.".format(len(g)))
# prints graph has 86 statements.

# print out the entire Graph in the RDF Turtle format
print(g.serialize(format="turtle").decode("utf-8"))

上例创建了一个Graph,并解析了一个RDF文件,该文件包含了Tim Berners-Lee的社交网络详细信息。 print()语句使用len()函数计算Graph中三元组的数量。

下面是官方给出的构建RDF文件的demo:

from rdflib import Graph, Literal, RDF, URIRef
# rdflib knows about some namespaces, like FOAF
from rdflib.namespace import FOAF , XSD

# create a Graph
g = Graph()

# Create an RDF URI node to use as the subject for multiple triples
donna = URIRef("http://example.org/donna")

# Add triples using store's add() method.
g.add((donna, RDF.type, FOAF.Person))
g.add((donna, FOAF.nick, Literal("donna", lang="ed")))
g.add((donna, FOAF.name, Literal("Donna Fales")))
g.add((donna, FOAF.mbox, URIRef("mailto:donna@example.org")))

# Add another person
ed = URIRef("http://example.org/edward")

# Add triples using store's add() method.
g.add((ed, RDF.type, FOAF.Person))
g.add((ed, FOAF.nick, Literal("ed", datatype=XSD.string)))
g.add((ed, FOAF.name, Literal("Edward Scissorhands")))
g.add((ed, FOAF.mbox, URIRef("mailto:e.scissorhands@example.org")))

# Iterate over triples in store and print them out.
print("--- printing raw triples ---")
for s, p, o in g:
    print((s, p, o))

# For each foaf:Person in the store, print out their mbox property's value.
print("--- printing mboxes ---")
for person in g.subjects(RDF.type, FOAF.Person):
    for mbox in g.objects(person, FOAF.mbox):
        print(mbox)

# Bind the FOAF namespace to a prefix for more readable output
g.bind("foaf", FOAF)

# print all the data in the Notation3 format
print("--- printing mboxes ---")
print(g.serialize(format='n3').decode("utf-8"))

RDF加载与保存

读取三元组文件

RDF数据具各种语法(xml、n3、nttriples、trix、JSON-LD等)。最简单的格式是ntples,一种基于行的格式。具体例子如下:

<http://bigasterisk.com/foaf.rdf#drewp> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> .
<http://bigasterisk.com/foaf.rdf#drewp> <http://example.com/says> "Hello world" .

读取文件需要通过格式关键字-参数parse()来解析,。如果不确定文件是什么格式,可以使用rdflib.util.guess_type(),它将根据文件扩展名来判断文件格式。加载例程如下所示:

from rdflib import Graph

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

print(len(g)) # prints 2

import pprint
for stmt in g:
    pprint.pprint(stmt)

# prints :
(rdflib.term.URIRef('http://bigasterisk.com/foaf.rdf#drewp'),
 rdflib.term.URIRef('http://example.com/says'),
 rdflib.term.Literal('Hello world'))
(rdflib.term.URIRef('http://bigasterisk.com/foaf.rdf#drewp'),
 rdflib.term.URIRef('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
 rdflib.term.URIRef('http://xmlns.com/foaf/0.1/Person'))

最后print的结果显示RDFLib如何表示文件中的两个语句。语句本身只是一条3元组;subjects, predicates, objects都是rdflib类型。

读取远程Graph

从网络上读取Graph:

g.parse("http://bigasterisk.com/foaf.rdf")
print(len(g))
# prints 42

格式默认为xml,这是常见的.rdf文件格式。 RDFLib还可以从任何类似的对象中读取RDF,即任何具有.read()方法的对象。

构建RDF文件

创建节点

RDF数据是一个图,其中节点是URI引用、空白节点或文字。在RDFLib中,这些节点类型由URIRef、BNode和Literal表示。URIRefs和BNodes都可以被视为资源,如个人、公司、网站等。

  • BNode是一个不知道确切URI的节点。

  • URIRef是已知确切URI的节点。

  • URIRefs还用于表示RDF图中的属性/谓词。

  • Literals表示属性值,如名称、日期、数字等。最常见的Literal是XML数据类型,例如string、int…

节点可以由节点类的构造函数创建:

from rdflib import URIRef, BNode, Literal

bob = URIRef("http://example.org/people/Bob")
linda = BNode()  # a GUID is generated

name = Literal('Bob')  # passing a string
age = Literal(24)  # passing a python int
height = Literal(76.5)  # passing a python float

Literals可以从Python对象创建,这将创建数据类型文字,有关映射的详细信息。

在同一命名空间中创建多个个URIRef,那么这些URL具有相同前缀。RDFLib具有rdflib.namespace.Namespace类:

from rdflib import Namespace

n = Namespace("http://example.org/people/")

n.bob  # = rdflib.term.URIRef(u'http://example.org/people/bob')
n.eve  # = rdflib.term.URIRef(u'http://example.org/people/eve')

RDFLib为一些常见的RDF/OWL模式定义了命名空间,包括大多数W3C模式:

from rdflib.namespace import CSVW, DC, DCAT, DCTERMS, DOAP, FOAF, ODRL2, ORG, OWL, \
                           PROF, PROV, RDF, RDFS, SDO, SH, SKOS, SOSA, SSN, TIME, \
                           VOID, XMLNS, XSD

RDF.type
# = rdflib.term.URIRef("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")

FOAF.knows
# = rdflib.term.URIRef("http://xmlns.com/foaf/0.1/knows")

PROF.isProfileOf
# = rdflib.term.URIRef("http://www.w3.org/ns/dx/prof/isProfileOf")

SOSA.Sensor
# = rdflib.term.URIRef("http://www.w3.org/ns/sosa/Sensor")

添加三元组

可以通过python 利用add()直接添加三元组。

add()采用RDFLib节点的三元组。具体操作如下:

from rdflib import Graph
g = Graph()
g.bind("foaf", FOAF)

g.add((bob, RDF.type, FOAF.Person))
g.add((bob, FOAF.name, name))
g.add((bob, FOAF.knows, linda))
g.add((linda, RDF.type, FOAF.Person))
g.add((linda, FOAF.name, Literal("Linda")))

print(g.serialize(format="turtle").decode("utf-8"))
outputs:
@prefix foaf: <http://xmlns.com/foaf/0.1/> .

<http://example.org/people/Bob> a foaf:Person ;
   foaf:knows [ a foaf:Person ;
           foaf:name "Linda" ] ;
   foaf:name "Bob" .

对于某些属性,每个资源只有一个值是有意义的(即它们是属性函数,或最大基数为1)。set()方法适用与这种属性:

g.add((bob, FOAF.age, Literal(42)))
print("Bob is ", g.value(bob, FOAF.age))
# prints: Bob is 42

g.set((bob, FOAF.age, Literal(43)))  # replaces 42 set above
print("Bob is now ", g.value(bob, FOAF.age))
# prints: Bob is now 43

rdflib.graph.Graph.value()是基于匹配的查询方法,它将返回单个属性值,如果有多个值,则会引发异常。

删除三元组

类似地,可以通过调用 remove()删除三元组。 删除时,可以让三元组的部分未指定(即传递无),这将删除所有匹配的三元组:

g.remove((bob, None, None)) # remove all triples about bob

动手实践

import rdflib
from rdflib import Literal
from rdflib.namespace import CSVW, DC, DCAT, DCTERMS, DOAP, FOAF, ODRL2, ORG, OWL, PROF, PROV, RDF, RDFS, SDO, SH, SKOS, SOSA, SSN, TIME

def create_rdf():
    g = rdflib.Graph()
    # 在命名空间'http://www.example.org/'中创建实体和关系
    # 实体
    zhangwuji = rdflib.URIRef('http://www.example.org/zhangwuji')
    baimeiyingwang  = rdflib.URIRef('http://www.example.org/baimeiyingwang')
    weifuwang = rdflib.URIRef('http://www.example.org/weifuwang')
    yangxiao = rdflib.URIRef('http://www.example.org/jinmaoshiwang')
    mingjiao = rdflib.URIRef('http://www.example.org/mingjiao')
    # 关系
    zhizhang = rdflib.URIRef('http://www.example.org/zhizhang')
    leader = rdflib.URIRef('http://www.example.org/leader')
    shuyu = rdflib.URIRef('http://www.example.org/shuyu')
    # 添加三元组
    g.add((zhangwuji, zhizhang, mingjiao))
    g.add((zhangwuji, shuyu, mingjiao))
    g.add((baimeiyingwang, leader, zhangwuji))
    g.add((weifuwang, leader, zhangwuji))
    g.add((yangxiao, leader, zhangwuji))
    # 保存RDF文件
    g.serialize('mingjiao.rdf')

if __name__ == "__main__":
    create_rdf()

上例中,首先创建实体:张无忌、白眉鹰王、韦幅王、杨逍,明教;关系:执掌,上层领导,属于。

其次,添加相应的三元组,如<张无忌,执掌,明教>。

最后,保存RDF文件。

想了解更多的AI技术干货,欢迎上华为云的AI专区,目前有AI编程Python等六大实战营供大家免费学习。(六大实战营link:http://su.modelarts.club/qQB9)

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。