前言
自由百科全书不仅仅应当可以自由编写,而更应该可以自由获得。
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查询(最好FQ,没FQ查询经常失败,不太明白为什么= =)。
不过这种查询最终返回结果是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 %20 where %20 {[] %20 a %20 ?Concept} %20 LIMIT %20 100
其中空格被转成%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>
}
}(
this
,
function
(){
'use strict'
function
SPARQLWrapper(endpoint){
this
.endpoint =
endpoint;
this
.queryPart = ""
;
this
.type = "json"
;
}
SPARQLWrapper.prototype
=
{
constructor: SPARQLWrapper,
setQuery:
function
(query){
this
.queryPart = "query=" +
encodeURI(query);
},
setType:
function
(type){
this
.type =
type.toLowerCase();
},
query:
function
(type, callback){
callback
= callback === undefined ? type :
this
.setType(type) ||
callback;
var
xhr =
new
XMLHttpRequest();
xhr.open(
'POST',
this
.endpoint,
true
);
xhr.setRequestHeader(
'Content-type', 'application/x-www-form-urlencoded'
);
switch
(
this
.type){
case
"json"
:
type
= "application/sparql-results+json"
;
break
;
case
"xml"
:
type
= "text/xml"
;
break
;
case
"html"
:
type
= "text/html"
;
break
;
default
:
type
= "application/sparql-results+json"
;
break
;
}
xhr.setRequestHeader(
"Accept"
, type);
xhr.onreadystatechange
=
function
(){
if
(xhr.readyState == 4
){
var
sta =
xhr.status;
if
(sta == 200 || sta == 304
){
callback(xhr.responseText);
}
else
{
console
&& console.error("Sparql query error: " + xhr.status + " " +
xhr.responseText);
}
window.setTimeout(
function
(){
xhr.onreadystatechange
=
new
Function();
xhr
=
null
;
},
0
);
}
}
xhr.send(
this
.queryPart);
}
}
return
SPARQLWrapper;
}));
使用方法,例如需要查询:
select distinct ?Concept where {[] a ?Concept} LIMIT 100
则该页面为:
<!
DOCTYPE html
>
<
html
xmlns
="http://www.w3.org/1999/xhtml"
>
<
head
>
<
meta
http-equiv
="Content-Type"
content
="text/html; charset=gb2312"
/>
<
script
src
="SPARQLWrapper.js"
type
="text/javascript"
></
script
>
</
head
>
<
body
>
<
script
>
var
sparql
=
new
SPARQLWrapper(
"
http://dbpedia.org/sparql
"
);
sparql.setQuery(
'
select distinct ?Concept where {[] a ?Concept} LIMIT 100
'
);
sparql.query(
function
(json){
console.log(
json
);
});
</
script
>
</
body
>
</
html
>
小例子
http://pan.baidu.com/share/link?shareid=293219&uk=855675565
修订记录
- 修正关于跨域的错误 2003.2.21

