如何使用 JSON 列出带有链接的维基百科页面标题?

How to list Wikipedia page titles with links using JSON?

这是我当前的代码。它完美地列出了页面标题,但链接都是 return 'undefined'.

function func(json) {
  var e = document.getElementById('wiki');
  var i;
  for (i=0; i < json.query.allpages.length; i++) {
    e.innerHTML += i + ": " + '<a href="' + "http://en.wikipedia.org/wiki/" +  json.query.link+ '">' +  json.query.allpages[i].title + '</a>' + "<br />";
  }
}

function getFromWikipedia() {
  var txt = document.getElementById('txt');
  var e = document.getElementById('wiki');
  var o = document.createElement("script");
      o.setAttribute("src", "http://en.wikipedia.org/w/api.php?action=query&list=allpages&format=json&apfrom="+txt.value+"&generator=alllinks&callback=func");
  e.appendChild(o);
}

将“&prop=links”and/or“&generator=alllinks”附加到 URL 似乎不会影响结果。

我想知道这部分应该包括什么:

'<a href="' + json.query.link+ '">'

以便列出页面标题及其各自的链接。 我已经尝试了 "json.query.allpages[i].pageID" 和 "json.query.alllinks",但一直没有用。

编辑: 放弃寻找 URL 转而使用 pageid 方法。

这样解决了:

e.innerHTML += i + ": " + '<a href="'+ "http://en.wikipedia.org/wiki/?curid="+  json.query.allpages[i].pageid + '">' +  json.query.allpages[i].title + '</a>' + "<br />";

您可以直接使用页面 ID 创建 link:

function func(json) {
  var e = document.getElementById('wiki');
  var i;
  for (i=0; i < json.query.allpages.length; i++) {
    e.innerHTML += i + ": " + '<a href="' + "http://en.wikipedia.org/?curid=" +  json.query.allpages[i].pageid+ '">' +  json.query.allpages[i].title + '</a>' + "<br />";
  }
}

在同一个查询中您同时拥有 list=generator= 这一事实向我表明您并不完全理解 generators 在 MediaWiki 中的工作方式 API.

基本上,生成器是一种使用 list as the source of pages to retrieve properties 的方式。 not 使用生成器作为另一个列表查询的输入没有任何意义。也就是说,您通常将 generator=prop= 一起使用, 而不是 list=。 MediaWiki(表面上)允许这样做的唯一原因是:

  1. 您可以使用页面列表(或生成器)进行查询,但没有 prop= 参数,like this。如果这样做,您只会获得页面的最小默认属性集(标题、命名空间和页面 ID)。

  2. 您还可以将属性查询和列表查询合并到一个请求中,like this. You'll just get the results for both queries, merged into the same JSON/XML/etc. output, but they'll be otherwise completely separate. (You can also make multiple simultaneous list queries 这样。)

因此,当您将 generator=list= 查询结合使用时,您将获得列表的常规输出和生成器匹配的页面的最小属性集。这两个输出不会以任何实际方式连接,除非是相同 API 响应的一部分。


无论如何,您想知道如何获取所有带有 links 的维基百科页面的标题和 URL。好吧,正如 schudel 在他们的回答中指出的那样,要获取某些页面的 URL,您需要 prop=infoinprop=url;对于 运行 所有 linked 页面上的此查询,您可以使用 generator=alllinks。因此,您最终得到:

请注意,这提供了所有包含 links from 的页面的信息。要运行查询所有link到的页面,需要加上参数galunique=true:

(是的,this is documented,虽然不是很清楚。)

显然,link 目标将包含大量缺失的页面。事实上 link sources 似乎还包含一个空标题的缺失页面,这大概是由于维基百科 link 数据库中的错误记录。这可以通过重建(冗余)links table 来解决,但是,考虑到维基百科的大小,这将花费相当多的时间(在此期间,据推测,该站点必须被锁定read-only 模式以避免进一步的不一致)。


要在 JavaScript 中处理这些数据,您可以这样做:

var apiURL = 'https://en.wikipedia.org/w/api.php?format=json&action=query&prop=info&inprop=url&generator=alllinks&callback=myCallback';

function myCallback(json) {
  var e = document.getElementById('wiki');
  for (var id in json.query.pages) {
    var page = json.query.pages[id];
    if (typeof(page.missing) !== 'undefined') continue;
    e.innerHTML += 
      id + ': <a href="' + escapeHTML(page.fullurl) + '">' + escapeHTML(page.title) + '</a><br />';
  }
  // handle query continuations:
  if (json.continue) {
    var continueURL = apiURL;
    for (var attr in json.continue) {
      continueURL += '&' + attr + '=' + encodeURIComponent(json.continue[attr]);
    }
    doAjaxRequest(continueURL);
}

doAjaxRequest(apiURL + '&continue=');

请注意,我还包含了一个处理 query continuations 的基本机制,因为您在使用 alllinks 时肯定需要处理这些机制。实现辅助函数 escapeHTML()doAjaxRequest() 留作练习。另请注意,我还没有实际测试过这段代码;我 认为 没问题,但可能存在我遗漏的错误。它还会产生一个长得离谱的列表,并且可能会使您的浏览器变慢以致于爬行,这仅仅是因为 Wikipedia 有 lot 个页面。对于实际应用程序,您可能希望引入某种 on-demand 加载方案(例如,仅当用户向下滚动到当前列表末尾时才加载更多结果)。