微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从 Wikidata 获取 geojson 数据

如何解决从 Wikidata 获取 geojson 数据

我请求维基数据实体并获取它们的 geoshape property (P3896)

例如 (try it):

SELECT ?item ?itemLabel ?geoshape ?geoshapeLabel
WHERE
{
  VALUES ?item { wd:Q142 }
  ?item wdt:P3896 ?geoshape.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}

所以我得到一个网址:http://commons.wikimedia.org/data/main/Data:France.map

我尝试使用 Javascript 获取数据:

  • fetch('http://commons.wikimedia.org/data/main/Data:France.map?origin=*')
  • fetch('https://commons.wikimedia.org/w/index.PHP?title=Data:France.map&action=raw&origin=*')

但是由于 CORS 政策我出错了:

请求中不存在“Access-Control-Allow-Origin”标头 资源。

有没有办法从 Web 应用程序的 Wikidata 中获取 geojson 数据?

解决方法

根据@Pascalo我们可以使用

fetch('https://commons.wikimedia.org/w/api.php?action=query&prop=revisions&rvslots=*&rvprop=content&format=json&titles=Data:France.map&origin=*')

从 Wikidata 获取 geojson 数据的完整 JS 解决方案如下:

class SPARQLQueryDispatcher {
  constructor(endpoint) {
    this.endpoint = endpoint;
  }
  query(sparqlQuery,simplify = true) {
    const fullUrl = this.endpoint + "?query=" + encodeURIComponent(sparqlQuery);
    const headers = {
      Accept: "application/sparql-results+json"
    };
    return fetch(fullUrl,{
        headers
      })
      .then(body => body.json())
      .then(data => (simplify ? this.simplify(data) : data));
  }
  simplify(data) {
    const bindings = data.results.bindings;
    return bindings.map(binding => {
      Object.keys(binding).forEach(function(key,index) {
        binding[key] = binding[key].value;
      });
      return binding;
    });
  }
}

function buildQuery(ids) {
  const wds = ids.map(id => `wd:${id}`).join(" ");
  return `
SELECT ?item ?itemLabel ?geoshape ?geoshapeLabel
WHERE
{
  VALUES ?item { ${wds} }
  ?item wdt:P3896 ?geoshape.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
`;
}

function fetchGeojson(rows) {
  const titles = rows
    .filter(r => r.geoshape)
    .map(r => r.geoshape.split("/data/main/").pop())
    .join("|");
  return fetch(`https://commons.wikimedia.org/w/api.php?action=query&prop=revisions&rvslots=*&rvprop=content&format=json&titles=${titles}&origin=*`)
    .then(r => r.json())
    .then(r => Object.values(r.query.pages))
    .then(r => r.map(r => JSON.parse(r.revisions[0].slots.main["*"]).data));
}

const queryDispatcher = new SPARQLQueryDispatcher("https://query.wikidata.org/sparql");
const query = buildQuery(["Q90"]); // Q90 = Paris

queryDispatcher
  .query(query)
  .then(fetchGeojson)
  .then(console.log);

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?