如何从Java访问Wikidata SPARQL接口?

5

我正在尝试从Wikidata查询一种实体的所有实例。我发现目前唯一的方法是使用SPARQL端点。

我找到了一个示例查询,它可以做到我想要的,并且在Web界面上成功执行了它。不幸的是,我似乎无法从我的Java代码中执行它。我正在使用openRDF SPARQL库。以下是我相关的代码:

SPARQLRepository sparqlRepository = new SPARQLRepository(
        "https://query.wikidata.org/");
SPARQLConnection sparqlConnection = new SPARQLConnection(
        sparqlRepository);

String query = "SELECT ?s ?desc ?authorlabel (COUNT(DISTINCT ?sitelink) as ?linkcount) WHERE {"
        + "?s wdt:P31 wd:Q571 ."
        + "?sitelink schema:about ?s ."
        + "?s wdt:P50 ?author"
        + "OPTIONAL { ?s rdfs:label ?desc filter (lang(?desc) = \"en\"). }"
        + "OPTIONAL {"
        + "?author rdfs:label ?authorlabel filter (lang(?authorlabel) = \"en\")."
        + "}"
        + "} GROUP BY ?s ?desc ?authorlabel ORDER BY DESC(?linkcount)";

TupleQuery tupleQuery = sparqlConnection.prepareTupleQuery(
        QueryLanguage.SPARQL, query);
System.out.println("Result for tupleQuery" + tupleQuery.evaluate());

这是我收到的响应:

Exception in thread "main" org.openrdf.query.QueryEvaluationException: <html>
<head><title>405 Not Allowed</title></head>
<body bgcolor="white">
<center><h1>405 Not Allowed</h1></center>
<hr><center>nginx/1.9.4</center>
</body>
</html>
    at org.openrdf.repository.sparql.query.SPARQLTupleQuery.evaluate(SPARQLTupleQuery.java:59)
    at main.Test.main(Test.java:72)
Caused by: org.openrdf.repository.RepositoryException: <html>
<head><title>405 Not Allowed</title></head>
<body bgcolor="white">
<center><h1>405 Not Allowed</h1></center>
<hr><center>nginx/1.9.4</center>
</body>
</html>
    at org.openrdf.http.client.HTTPClient.handleHTTPError(HTTPClient.java:953)
    at org.openrdf.http.client.HTTPClient.sendTupleQueryViaHttp(HTTPClient.java:718)
    at org.openrdf.http.client.HTTPClient.getBackgroundTupleQueryResult(HTTPClient.java:602)
    at org.openrdf.http.client.HTTPClient.sendTupleQuery(HTTPClient.java:367)
    at org.openrdf.repository.sparql.query.SPARQLTupleQuery.evaluate(SPARQLTupleQuery.java:52)
    ... 1 more

通常我会认为这意味着我需要某种API密钥,但Wikidata API似乎是完全开放的。我设置连接时犯了错误吗?

另请参阅 使用Jena查询wikidata - Joshua Taylor
2个回答

6

Wikidata的正确终端节点URL为https://query.wikidata.org/sparql ——你遗漏了最后一部分。

此外,我注意到你的代码有几个小问题。首先,你正在执行以下操作:

SPARQLConnection sparqlConnection = new SPARQLConnection(sparqlRepository);

这应该变成这样:

RepositoryConnection sparqlConnection = sparqlRepository.getConnection();

在处理数据库连接时,应该从 Repository 对象中使用 getConnection() 方法来获取连接对象。这样可以共享资源,并且如果需要,Repository 可以关闭未正常关闭的连接。

其次,不能像下面这样直接打印查询结果:

System.out.println("Result for tupleQuery" + tupleQuery.evaluate());

如果您希望将结果打印到 System.out 中,您应该采取以下做法:
tupleQuery.evaluate(new SPARQLResultsTSVWriter(System.out));

或者(如果您希望进一步自定义结果):
for (BindingSet bs : QueryResults.asList(tupleQuery.evaluate())) {
    System.out.println(bs);
}

就我所知 - 经过上述更改后,查询请求可以正常运行,但似乎您的查询对Wikidata来说太“繁重”了 - 至少服务器会超时错误。尝试一个简单的查询,您将看到代码可以工作。


谢谢您提供这些有用的提示。我使用Sysout作为测试,它应该调用tupleQuery.evaluate()的toString()方法,这足以看出它是否起作用。 - Andreas Hartmann

4
当我访问https://query.wikidata.org/并查看“工具”>“SPARQL REST终端”时,我看到(重点添加):
SPARQL终端 可以使用GET请求直接向SPARQL终端提交SPARQL查询,如https://query.wikidata.org/sparql?query={SPARQL}(将拒绝POST和其他方法请求,返回“403 Forbidden”)。默认情况下返回XML结果,如果提供查询参数格式=json或标题Accept: application/sparql-results+json,则返回JSON结果。
看起来你正在使用不同的URL(它看起来没有最终的sparql),所以你可能实际上没有命中该端点。
话虽如此,既然你可以访问你正在使用的URL(可能使用GET),那么你的API调用可能正在进行POST,因此您还需要检查查询在网络上传输的方式。

这个端点的使用示例可以在使用Jena查询Wikidata中找到。那个问题的OP实际上遇到了你遇到的相同问题(错误的查询URL)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接