Wikidata のクエリサービスは SPARQL による検索に対応しており、さまざまな知識を取得できます。
SPARQL 検索は GET や POST を直接使って実行することも可能ですが、SPARQL や RDF に対応したライブラリを利用すると便利な機能を活用できます。代表的なライブラリのひとつが、Java で開発された Apache Jena です。
私は普段 Java を使うことが多いため、SPARQL の処理には Jena を利用していました。ところが最近、
これまで問題なく動いていた Jena を使った SPARQL プログラムが、Wikidata に対して実行すると 403 エラーで失敗する!
という現象に遭遇しました。
以下はそのときのコード例です。
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryExecution;
import org.apache.jena.query.QueryFactory;
import org.apache.jena.query.ResultSet;
import org.apache.jena.query.ResultSetFormatter;
import org.apache.jena.sparql.exec.http.QueryExecutionHTTP;
public class WikidataQueryExample {
public static void main(String[] args) {
// SPARQL Endpoint の設定
String endpoint = "https://query.wikidata.org/sparql";
// SPARQL クエリの記述
String queryStr = """
SELECT *
WHERE {
<http://www.wikidata.org/entity/Q17> ?p ?o .
} LIMIT 100
""";
Query query = QueryFactory.create(queryStr);
try (QueryExecution qExec = QueryExecutionHTTP.create()
.endpoint(endpoint)
.query(query)
.param("timeout", "10000")
.build()) {
// クエリの実行
ResultSet rs = qExec.execSelect();
ResultSetFormatter.out(System.out, rs, query);
}
}
}
このコードは以前は問題なく動作していましたし、Wikidata 以外の SPARQL エンドポイントでは今でも動作します。にもかかわらず、Wikidata に対して実行すると次のように 403 エラーが発生します。
Exception in thread "main" HttpException: 403 Forbidden
at org.apache.jena.sparql.engine.http.QueryExceptionHTTP.rewrap(QueryExceptionHTTP.java:49)
at org.apache.jena.sparql.exec.http.QueryExecHTTP.executeQuery(QueryExecHTTP.java:552)
...
at WikidataQueryExample.main(WikidataQueryExample.java:43)
調べてみると、その原因は User-Agent ヘッダの制限 にあることが分かりました。
自動アクセスを行う場合、User-Agent ヘッダに「連絡先が分かる情報(メールアドレスやツールの URL)」を含める必要があります。これは、Wikidata チームが問題発生時に連絡できるようにするためです。
デフォルトのcurl/7.x
やPython-requests/2.x
のままではアクセス制限されることがあります。
(おそらくサーバ側のアップデートで制限が厳しくなったと思われます。)
そこで、Jena を用いたコードを次のように修正しました。
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryExecution;
import org.apache.jena.query.QueryFactory;
import org.apache.jena.query.ResultSet;
import org.apache.jena.query.ResultSetFormatter;
import org.apache.jena.sparql.exec.http.QueryExecutionHTTP;
public class WikidataQueryExample {
public static void main(String[] args) {
// User-Agent の情報を設定(自身のシステム情報に書き換えること)
String ua = "Example-Agent/1.0 (https://www.example.com; xxx@example.com)";
// SPARQL Endpoint の設定
String endpoint = "https://query.wikidata.org/sparql";
// SPARQL クエリの記述
String queryStr = """
SELECT *
WHERE {
<http://www.wikidata.org/entity/Q17> ?p ?o .
} LIMIT 100
""";
Query query = QueryFactory.create(queryStr);
try (QueryExecution qExec = QueryExecutionHTTP.create()
.endpoint(endpoint)
.query(query)
.httpHeader("User-Agent", ua)
.param("timeout", "10000")
.build()) {
// クエリの実行
ResultSet rs = qExec.execSelect();
ResultSetFormatter.out(System.out, rs, query);
}
}
}
String ua = "Example-Agent/1.0 (https://www.example.com; xxx@example.com)";
で User-Agent を指定し、
.httpHeader("User-Agent", ua)
でヘッダに追加することで、無事に Wikidata にクエリを実行できるようになりました。
なお、別の Java ライブラリである RDF4J では、User-Agent を明示的に指定しなくても Wikidata にアクセスできるようです(ただし自分では未検証)。
以上のことから、この問題は
- Apache Jena を使用し、
- Wikidata の SPARQL endpoint にクエリを投げる場合
という限定的な条件で発生するようです。
今後のための備忘録として記録しておきます。
追記(2025.9.2)
この記事で記載した「WikidataのSPARQL検索で403エラーが出る現象」は,現時点(2025.9.2)では解消しているようです.
ただ,この記事で紹介した「User-Agentを指定しての検索」は,そのまま使用できますので,今後,同様の問題が発生することを避けるために使っても良いかもしれません.