如何从 Java 访问维基数据 SPARQL 界面?
How to access the Wikidata SPARQL interface from Java?
我正在尝试从维基数据中查询一个实体的所有实例。我发现目前唯一的方法是使用 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 密钥,但维基数据 API 似乎是完全开放的。我设置连接有误吗?
当我转到 https://query.wikidata.org/ 并查看工具 > SPARQL REST 端点时,我看到(强调):
SPARQL endpoint
SPARQL queries can be submitted directly to the SPARQL endpoint with a GET request to https://query.wikidata.org/sparql?query={SPARQL} (POST and other method requests will be denied with a "403 Forbidden").* The result is returned as XML by default, or as JSON if either the query parameter format=json or the header Accept: application/sparql-results+json are provided.
看起来您使用的是不同的 URL(看起来您没有最后的 sparql
),所以您可能实际上没有达到那个终点。
也就是说,由于您可以访问 正在 使用的 URL(大概使用 GET),听起来您的 API 调用可能是执行 POST,因此您可能还想检查查询是如何通过网络进行的。
在 中有一个使用 Jena 的这个端点的例子。该问题的 OP 实际上与您 运行 遇到的问题相同(错误的查询 URL)。
维基数据的正确端点 URL 是 https://query.wikidata.org/sparql
- 你漏掉了最后一点。
此外,我注意到您的代码中存在一些小问题。首先,您要这样做:
SPARQLConnection sparqlConnection = new SPARQLConnection(sparqlRepository);
应该是这样的:
RepositoryConnection sparqlConnection = sparqlRepository.getConnection();
始终使用 getConnection()
从 Repository
对象检索连接对象 - 这意味着资源是共享的,Repository
可以在必要时关闭 'dangling' 连接。
其次:你不能像这样打印出查询结果:
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 来说太 'heavy' - 至少我从服务器收到超时错误。不过尝试一个更简单的查询,您会看到代码有效。
我正在尝试从维基数据中查询一个实体的所有实例。我发现目前唯一的方法是使用 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 密钥,但维基数据 API 似乎是完全开放的。我设置连接有误吗?
当我转到 https://query.wikidata.org/ 并查看工具 > SPARQL REST 端点时,我看到(强调):
SPARQL endpoint
SPARQL queries can be submitted directly to the SPARQL endpoint with a GET request to https://query.wikidata.org/sparql?query={SPARQL} (POST and other method requests will be denied with a "403 Forbidden").* The result is returned as XML by default, or as JSON if either the query parameter format=json or the header Accept: application/sparql-results+json are provided.
看起来您使用的是不同的 URL(看起来您没有最后的 sparql
),所以您可能实际上没有达到那个终点。
也就是说,由于您可以访问 正在 使用的 URL(大概使用 GET),听起来您的 API 调用可能是执行 POST,因此您可能还想检查查询是如何通过网络进行的。
在
维基数据的正确端点 URL 是 https://query.wikidata.org/sparql
- 你漏掉了最后一点。
此外,我注意到您的代码中存在一些小问题。首先,您要这样做:
SPARQLConnection sparqlConnection = new SPARQLConnection(sparqlRepository);
应该是这样的:
RepositoryConnection sparqlConnection = sparqlRepository.getConnection();
始终使用 getConnection()
从 Repository
对象检索连接对象 - 这意味着资源是共享的,Repository
可以在必要时关闭 'dangling' 连接。
其次:你不能像这样打印出查询结果:
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 来说太 'heavy' - 至少我从服务器收到超时错误。不过尝试一个更简单的查询,您会看到代码有效。