前言 自由百科全书不仅仅应当可以自由编写,而更应该可以自由获得。
DBpedia对Wikipedia的数据变成Linked Data形式,使得机器也能读懂并自由获得这些数据。
本文的主要目的是利用Javascript从DBpedia中获取我们想要的数据。
对Linked Data不太了解的请参考:
关联数据入门——RDF。
SPARQL Trying to use the Semantic Web without SPARQL is like trying to use a relational database without SQL.
—— Tim Berners-Lee
SPARQL是Semantic Web(语义网)的SQL,用于数据查询的语言。
SPARQL Endpoint SPARQL查询终端,是一种HTTP绑定协议,用于通过HTTP进行SPARQL查询,并返回相应数据。
DBpedia的SPARQL Endpoint地址是:http://dbpedia.org/sparql
大家可以通过浏览器打开这个页面,进行SPARQL查询(最好翻墙,没翻墙查询经常失败,不太明白为什么= =)。
不过这种查询最终返回结果是HTML页面,并不是我们想要的,我们可以通过设置Request Header的Accept属性来指定返回数据类型。
例如如果指定为:text/xml,那么返回的便是RDF格式数据。
那么我们如何输入SPARQL查询代码呢?
只需通过get或者post方法用参数query,将代码传过去。例如:
如果想查询:select distinct ?Concept where {[] a ?Concept} LIMIT 100
则可利用该链接得到数据:
http://dbpedia.org/sparql?query=select%20distinct%20?Concept%20where%20{[]%20a%20?Concept}%20LIMIT%20100
其中空格被转成%20。
实现细节 •跨域
我们可以通过AJAX实现这一功能,但是AJAX在部分浏览器中无法跨域,然而很显然我们想要的Linked Data几乎都是跨域的。
实际上,在一些较老版本的浏览器,我们没有不改变其数据形式的方法在前端进行动态跨域异步读取。
不过我们可以通过服务器代理的方法来解决跨域问题。
•GET or POST
使用GET还POST呢?
这个可能出于很多方面考虑,但是考虑到GET可能被缓存,所以我们使用POST来避免数据被缓存。
•以什么形式返回数据
前面我们说到用text/xml可以返回RDF数据,但是RDF在Javascript中并不好处理,所以我们使用json方式返回,也就是需要将Accept设置成application/sparql-results+json。
实现 接口参考Python的SPARQL Wrapper
(function(root, factory) {
if(typeof define === "function"){
define("SPARQLWrapper", factory); // AMD || CMD
}else{
root.SPARQLWrapper = factory(); // <script> <BR>} <BR>}(this, function(){ <BR>'use strict' <BR>function SPARQLWrapper(endpoint){ <BR>this.endpoint = endpoint; <BR>this.queryPart = ""; <BR>this.type = "json"; <BR>} <BR>SPARQLWrapper.prototype = { <BR>constructor: SPARQLWrapper, <BR>setQuery: function(query){ <BR>this.queryPart = "query=" + encodeURI(query); <BR>}, <BR>setType: function(type){ <BR>this.type = type.toLowerCase(); <BR>}, <BR>query: function(type, callback){ <BR>callback = callback === undefined ? type : this.setType(type) || callback; <BR>var xhr = new XMLHttpRequest(); <BR>xhr.open('POST', this.endpoint, true); <BR>xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); <BR>switch(this.type){ <BR>case "json": <BR>type = "application/sparql-results+json"; <BR>break; <BR>case "xml": <BR>type = "text/xml"; <BR>break; <BR>case "html": <BR>type = "text/html"; <BR>break; <BR>default: <BR>type = "application/sparql-results+json"; <BR>break; <BR>} <BR>xhr.setRequestHeader("Accept", type); <BR>xhr.onreadystatechange = function(){ <BR>if(xhr.readyState == 4){ <BR>var sta = xhr.status; <BR>if(sta == 200 || sta == 304){ <BR>callback(xhr.responseText); <BR>}else{ <BR>console && console.error("Sparql query error: " + xhr.status + " " + xhr.responseText); <BR>} <BR>window.setTimeout(function(){ <BR>xhr.onreadystatechange= new Function(); <BR>xhr = null; <BR>},0); <BR>} <BR>} <BR>xhr.send(this.queryPart); <BR>} <BR>} <BR>return SPARQLWrapper; <BR>})); <BR></script>
使用方法,例如需要查询:
select distinct ?Concept where {[] a ?Concept} LIMIT 100
则该页面为:
<script> <BR>var sparql = new SPARQLWrapper("http://dbpedia.org/sparql"); <BR>sparql.setQuery('select distinct ?Concept where {[] a ?Concept} LIMIT 100'); <BR>sparql.query(function(json){ <BR>console.log(eval('(' + json + ')'); <BR>}); <BR></script>
灏