【问题标题】:How to get property labels from Wikidata using SPARQL如何使用 SPARQL 从 Wikidata 获取属性标签
【发布时间】:2019-06-07 01:21:39
【问题描述】:

我正在使用 SPARQLWrapper 将 SPARQL 查询发送到 Wikidata。 目前我正在尝试查找实体的所有属性。例如。使用一个简单的元组,例如:wd:Q11663 ?a ?b. 这本身就可以工作,但我正在尝试为返回的属性和实体找到人类可读的标签。

虽然SERVICE wikibase:label 使用 Wikidata 的 GUI 界面,但这不适用于 SPARQLWrapper - 它坚持为变量及其“标签”返回相同的值。

对属性 rdfs:label 的查询适用于实体 (?b),但此方法不适用于属性 (?a)。

看起来该属性正在以完整 URI 的形式返回,例如 http://www.wikidata.org/prop/direct/P1536 。使用 GUI 我可以成功查询wd:P1536 ?a ?b.。如果我将它作为第二个查询发送,这适用于 SPARQLWrapper - 但不是在第一个查询中。

这是我的代码:

from SPARQLWrapper import SPARQLWrapper, JSON

sparql = SPARQLWrapper("http://query.wikidata.org/sparql")

sparql.setQuery("""
  SELECT ?a ?aLabel ?propLabel ?b ?bLabel
  WHERE
  {
    wd:Q11663 ?a ?b.

    # Doesn't work with SPARQLWrapper
    #SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
    #?prop wikibase:directClaim ?p

    # but this does (and is more portable)
    ?b rdfs:label ?bLabel. filter(lang(?bLabel) = "en").

    # doesn't work
    #?a rdfs:label ?aLabel. 

    # property code can be extracted successfully
    BIND(  strafter(str(?a), "prop/direct/") AS ?propLabel).
    #BIND( CONCAT("wd:", strafter(str(?a), "prop/direct/") ) AS ?propLabel).

    # No matches, even if I concat 'wd:' to ?propLabel
    ?propLabel rdfs:label ?aLabel
    # generic search for any properties also fails
    #?propLabel ?zz ?aLabel.
   }
 """)

# However, this returns a label for P1536 - which is one of wd:Q11663's properties
sparql.setQuery("""SELECT ?b WHERE
   {
      wd:P1536 rdfs:label ?b.
   }
""")

那么如何在一个查询中获取属性的标签(应该更有效)?

[顺便说一句:是的,我有点粗鲁并且准备好使用 EN 过滤器 - 如果我没有得到任何回报,通常会放弃它]

【问题讨论】:

  • 您的查询有点混乱。您说它不适用于标签服务,但您使用了#?prop wikibase:directClaim ?p,而在上面的三重模式中,该属性称为?a。那确实行不通。您还必须将?b rdfs:label ?bLabel. filter(lang(?bLabel) = "en"). 之类的内容放入OPTIONAL 子句中,否则您将不会得到任何没有标签的文字值。 BIND( strafter(str(?a), "prop/direct/") AS ?propLabel). 行使 propLabel 成为纯字符串文字,因此 ?propLabel rdfs:label ?aLabel 无法工作。
  • 我的建议:SELECT ?a ?propLabel ?b ?bLabel WHERE { wd:Q11663 ?a ?b. SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } ?prop wikibase:directClaim ?a . }
  • @AKSW:是的,对我们所有人来说有点困惑 - 我在 SPARQL 的学习曲线上处于早期阶段:-)。我根本没有尝试使用 directClaim,因为 SERVICE 行不适用于 SPARQLWrapper。我刚刚尝试了您的建议,并且看起来可行-谢谢。我需要阅读 directClaim 等内容。
  • 重新。字符串文字:我想知道这是不是发生了什么,但我找不到将字符串文字转换为元素的方法。如何在不依赖 Wikidata 扩展的情况下以通用/标准 SPARQL 方式获取属性标签?
  • @AKSW :好的,我已经通过您的代码与我的代码进行了比较。我相信我现在明白发生了什么 - 谢谢!如果找不到任何东西,标签服务看起来会默认为实体值 - 所以看起来结果很混乱并返回相同的实体名称和标签。实际上有些是,有些不是。将 OPTIONAL 添加到 rdfs:label 子句中突出显示了这一点。我现在也了解 wikibase:directClaim - 真的很简单!欢迎您将其作为答案发布,或者我可以使用我的代码和我理解的解释发布答案。

标签: sparql wikidata sparqlwrapper


【解决方案1】:

我在使用两种方法时遇到了问题 - 上面的代码同时包含了这两种方法。此外,SPARQLWrapper 在这里也不是问题。

第一种使用wikibase标签服务的方法应该是这样的:

SELECT ?a ?aLabel ?propLabel ?b ?bLabel
WHERE
{
  ?item rdfs:label "weather"@en.
  ?item ?a ?b.

  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } 
  ?prop wikibase:directClaim ?a .
}

此代码还包括从标签(“天气”)到查询实体(?item)的查找。

SERVICE 正在工作,但如果没有 rdfs:label 定义,那么它只会返回实体。 GUI 和 SPARQLWrapper(到 SPARQL 端点)只是以不同的顺序返回结果 - 所以看起来我看到了很多“失败”的输出(即实体和失败的标签都被报告为相同的)。

当我开始在下面的方法中添加一个 OPTIONAL 子句时,这一点变得很清楚。

?prop wikibase:directClaim ?a . 行非常简单。 Wikibase 定义 directClaim 将属性映射到实体。这允许它定义关于属性的元组(即标签)。许多其他本体只是使用相同的标识符。

我的第二个(更通用的方法)是您在许多书籍和在线教程中找到的方法。这里的问题是 wikibase 的属性中包含完整的 URL,我需要将它们转换为实体。我尝试了字符串操作,但这会产生一个字符串文字 - 而不是一个实体。解决方法是再次使用directClaim

?prop wikibase:directClaim ?a .
?prop rdfs:label ?propLabel.  filter(lang(?propLabel) = "en").

请注意,只有在定义了rdfs:label 时才会返回结果。即使没有定义标签,添加 OPTIONAL 也会返回结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-25
    • 1970-01-01
    相关资源
    最近更新 更多