首页 > 解决方案 > 从 Wikidata 中提取 RDF 三元组

问题描述

我正在按照指南从 Wikidata 进行查询。

我可以使用以下方法获取某个实体(如果我知道它的代码):

from wikidata.client import Client
client = Client()
entity = client.get('Q20145', load=True)
entity
>>><wikidata.entity.Entity Q20145 'IU'>
entity.description
>>>m'South Korean singer-songwriter, record producer, and actress'

但是我怎样才能得到那个实体的 RDF 三元组呢?即所有以(主语、谓语、宾语)形式的出边和入边

看起来这个SO question 设法获得了三元组,但只能从这里的数据转储中获得。我正在尝试从图书馆本身获取它。

标签: pythondatabaserdfwikidata

解决方案


如果您只需要传出边,您可以通过调用https://www.wikidata.org/wiki/Special:EntityData/Q20145.nt直接检索它们

from rdflib import Graph
g = Graph()
g.parse('https://www.wikidata.org/wiki/Special:EntityData/Q20145.nt', format="nt")    
for subj, pred, obj in g:
    print(subj, pred, obj)

要获取传入和传出边,您需要查询数据库。在 Wikidata 上,这是使用Wikidata 查询服务和查询语言 SPARQL 完成的。获取所有边的 SPARQL 表达式就像DESCRIBE wd:Q20145.

使用 Python,您可以使用以下代码检索查询结果:

import requests
import json

endpoint_url = "https://query.wikidata.org/sparql"
headers = { 'User-Agent': 'MyBot' }
payload = {
    'query': 'DESCRIBE wd:Q20145',
    'format': 'json'
}
r = requests.get(endpoint_url, params=payload, headers=headers)
results = r.json()

triples = []
for result in results["results"]["bindings"]:   
    triples.append((result["subject"], result["predicate"], result["object"]))
print(triples)

这为您提供了来自复杂基础数据模型的完整结果来源。如果要分别查询传入和传出边,请编写而不是DESCRIBE wd:Q20145CONSTRUCT {?s ?p ?o} WHERE {BIND(wd:Q20145 AS ?s) ?s ?p ?o}具有传出边或CONSTRUCT {?s ?p ?o} WHERE {BIND(wd:Q20145 AS ?o) ?s ?p ?o}仅具有传入边。

根据您的目标,您可能希望过滤掉一些三元组,例如语句三元组,并且您可能希望简化一些三元组。获得更清晰结果的一种可能性是将最后四行替换为:

triples = []
for result in results["results"]["bindings"]:   
    subject = result["subject"]["value"].replace('http://www.wikidata.org/entity/', '')
    object = result["object"]["value"].replace('http://www.wikidata.org/entity/', '')
    predicate = result["predicate"]["value"].replace('http://www.wikidata.org/prop/direct/', '')
    if 'statement/' in subject or 'statement/' in object:
        continue
    triples.append((subject, predicate, object))
print(triples)

推荐阅读