修改藏书小工具代码的过程中,我第一次真正接触MediaWiki的API。我本以为自己一直都不可能有机会用到API,虽然很多人都会提到使用API会让日常工作事半功倍。
可它不是开发人员才能用到的吗,跟普通用户又有什么关系呢?尤其是很多人跟我一样对编程一窍不通,用API又能做些什么呢?
事实上,通过使用API沙盒,我们可能无需编写任何一行代码就可以使用API做许多很酷的事情。当然如果你还具备一定的编程能力那就更好了。即便你最终也写了些代码,那么在开始前使用沙盒也可以让你更好地过渡到执行一些基本开发任务。
API沙盒内置于MediaWiki中,无需进行任何特殊配置就可以使用。你只需要在维基站点中打开Special:ApiSandbox页面(注意大小写,即便它与“API”不匹配),然后你就可以开始用GUI的交互方式进行操作了。让我们快速浏览一下其中的一些操作——其中一些主要是从学习角度来看很有用,而另一些可能是以后会定期使用的工具。
首先是“action”输入框,我们会在其中输入想要执行的操作:
API沙盒.png
在该下拉列表中,你可以从中选择想要执行的操作类型。以下是你可能会用到的某些操作:

  • query- 获取有关页面、修订、分类、报告(如双重重定向)等的信息。这可能是你最常用的操作。
  • edit- 编辑页面。你可以替换其整个文本、附加一些东西、预先考虑的某些内容,甚至只是空白/空编辑来刷新缓存。
  • delete- 删除一个页面或一组页面(如果有垃圾邮件机器人攻击,创建了大量的页面,这会很有用)。
  • move- 移动页面。
  • pfautoedit- 这是由PageForms扩展提供的,我们稍后会讨论它——这可能是最简单的有用操作。
  • parse- 如果你想延迟加载 wiki 页面的一部分,你可能会使用此操作来创建可以插入到 DOM 中的 HTML(如果你不知道这意味着什么,请不要担心)。

让我们看一下pfautoedit,因为这是最简单的操作之一。如果你不使用页面表单,则可以跳过下一段(这解释了我们可能要使用它的原因),并跳转到后面的段落(解释了如何操作)。
为什么使用pfautoedit?当你对表单进行更改(例如添加复选框或更改两个参数的顺序)时,提交时保存到页面的 wiki 文本会发生更改。如果添加复选框,扩展名将添加值Yes或No。如果更改参数的顺序,扩展将更改先前给定参数的顺序。这可能会导致大量不相关的“垃圾邮件”占据已包含旧维基文本保存版本的页面上的大部分未来差异。有时这没什么大不了的,但如果你做了很多改变——或者如果你必须非常密切地关注新的修订——那么处理起来可能会很烦人。幸运的是,该扩展提供了一种内置的方法来处理这个问题!pfautoedit操作将“表单编辑”应用于你发送到的每个页面。(请注意,扩展程序文档中概述了其他自动执行此操作的方法。)
如何使用pfautoedit?如果你跳过了上一段,欢迎回来!让我们逐步了解如何使用此操作——对于你可能采取的任何操作,这都是相同的基本过程。
API沙盒action选择.png
请注意左侧栏上增加了一个新项,上面写着action=pfautoedit。点击后,将看到一个类似这样的页面:
API沙盒action=pdautoedit.png
现在是你希望有好的文档说明你想做什么,尽管有时你只能猜测。你应该在 mediawiki.org上的API手册添加书签以便随时获取文档。如果你正在使用扩展程序的API,例如Page Forms的pfautoedit,你可以查看扩展程序的文档,甚至可以联系开发人员。也就是说,有时即使在你正在使用的新操作类型上,你也会发现一些熟悉的字段——例如,许多操作都有一个名为“Title”的字段,需要你为其指定页面标题。
在本例中,pfautoedit需要填写两个字段——表单(form)和目标(target)。目标只是页面标题,表单是你希望应用的表单的名称,不带前缀Form:。因此,如果我们想将表单Person到页面西格蒙德·弗洛伊德,我们可以向其发送以下输入内容:
API沙盒action=pdautoedit选项.png

警告:你在API:Sandbox中所做的每个操作都会在你的wiki上运行并产生实际效果!这不是一个安全的测试沙盒游乐场!请注意后果!!!
在本例中,西格蒙德·弗洛伊德条目的信息框就被清空了,因为表单关联的就是人物信息框。
API沙盒action结果.png
我在这个结果中对几个项目进行了编号。让我们逐一了解下:

  1. 其中显示“URL查询字符串”的地方,这是你刚刚输入的内容的摘要。你可以单击它来显示 JSON 格式。

    • 例如,如果你希望能够为URL添加书签以按需执行此操作,则URL表单非常有用——不过,通常我希望为查询执行此操作,而不是执行某个操作。
    • 如果你想要编写代码并将所有参数写成漂亮、整洁的JSON(基本上是你放入其中的参数的一组键值对),则JSON形式非常有用。
  2. 下面的框显示你在第1部分中选择的内容。
  3. 主要结果部分显示成功或失败(如果你执行了某些操作)或查询的结果(如果你进行了某些查询操作)。在本例中,这是一条成功消息。
  4. 如果我们想返回并编辑pfautoedit操作页面中的参数,我们可以单击此处然后再次运行。
  5. 如果我们想第二次运行完全相同的请求,我们可以再次单击“提交请求”。单击“清除”将使我们回到最开始,也就是我们选择操作之前。

现在我们已经了解了如何输入参数并获取结果的简单案例,让我们看一下你可能想要执行的query操作示例。即使你没有安装页面表单(Page Forms),这也是你应该能够跟随的示例。

单击“清除”然后返回第一个屏幕,点击action下拉菜单中的query选项,再单击ation=query侧边栏。现在,在action=query设置页面上,有两个重要字段需要理解:

  • prop- 这些是你可能想要请求的单个页面的属性。如果你想检索页面的文本、需要请求最新的修订版本、并获取该页面的文本。在query模块中,页面的文本属于修订版,而不属于页面。你还可以获取诸如页面的categorieslinkshere之类的内容。你可以同时选择多个内容进行查询——例如,你可以同时请求linksheretranscledin,以获取链接到特定页面或链入页面的页面(“transcluded”是你使用模板时所做的操作,例如{{模板:信息框}}“链入”页面模板:信息框。)
  • list- 这些是你可以检索的页面、修订、日志、文件等的列表。不同类型的列表需要为其提供不同的参数。例如,categorymembers希望你告诉它一个分类以赋予其成员。recentchanges希望你告诉它获取修订的时间间隔。querypage希望你为其指定一个特殊页面的名称(例如,DoubleRedirects),它将为你检索。

让我们选择linksheretranscludedin

至此,你可能已经理解为了阅读文档并弄清楚如何使用API所需的一切!从下拉列表中选择一个,然后选择另一个。顺便说一句,如果你单击字段下方的[展开] 按钮,大多数字段都会为你提供一些说明。
花点时间看看左栏——实际上还有另一组页面,我们可以单击并在其中输入信息!但是首先,我们必须向我们的query提供更多信息。
向下滚动页面,找到titles。在你的wiki上选择一个你想要查看其信息的页面;例如,在心百科上我可以选择“西格蒙德·弗洛伊德”。请注意一件事——在我们看到的pfautoedit示例中,我们只是在字段中输入值,没什么大不了的。但对于某些字段,例如titles,wiki希望对你的输入进行一些验证。根据你的 MediaWiki版本,你可能需要在输入内容后按回车键,并且再框外选择或单击是不够的。它应该在页面名称周围画一个带有 X(将其删除)的小椭圆形。
如果你愿意,可以在此处的框中输入两个或多个页面名称。每个标题都应该在其周围绘制自己的小椭圆形(因此,在 MediaWiki 的某些版本中,你可能必须在每个标题后按回车键)。我还将添加“精神分析”,这是心理学家“西格蒙德·弗洛伊德”所开创的心理学流派。
现在让我们返回到左列,其中包含新链接:prop=transcludedinprop=linkshere。这意味着我们应该指定(或故意保留默认值)的每个属性都有一些唯一的数据。这些选项页面都没有什么特别之处,因此只需看一下它们,注意它们是如何工作的,然后就这样——请记住,你可以稍后重做查询。

因为我们正在执行查询操作,所以不必担心意外破坏某些内容,因此请继续点击“提交请求”。这是我的wiki上的报告(出于说明目的,我将transcludedinlinkshere限制为1):

我给出的输入参数(在中文环境下,如果不开启utf8和ascii的话中文字符就会变成转义字符):

{
    "action": "query",
    "format": "json",
    "prop": "transcludedin|linkshere",
    "continue": "||",
    "titles": "西格蒙德·弗洛伊德|精神分析",
    "tilimit": "1",
    "lhlimit": "1",
"utf8": 1,
"ascii": 1
}

然后输出:

{
    "continue": {
        "lhcontinue": "精神分析|68",
        "continue": "||transcludedin"
    },
    "query": {
        "pages": {
            "2632": {
                "pageid": 2632,
                "ns": 0,
                "title": "精神分析",
                "linkshere": [
                    {
                        "pageid": 3,
                        "ns": 0,
                        "title": "心理学家列表"
                    }
                ]
            },
            "68": {
                "pageid": 68,
                "ns": 0,
                "title": "西格蒙德·弗洛伊德"
            }
        }
    }
}

API沙盒action=query结果.png
因此,如果我们想在第一个1之后获得更多结果(或你设置的任何限制),则第一部分说继续,将提供信息。如果你检索了完整的结果集,那将不存在。你可能需要滚动才能查看它,但是在响应下面有一个按钮,上面写着“继续”,以及另一个“清除”按钮。正如这些按钮右侧的信息图标所指出的那样:“继续将继续上次请求;清除将清除继续相关的参数。”
如果我们将整个响应命名为response,那么包含信息的结果将包含在response['query']['pages']中。之所以说query是因为我们做了一个查询动作。如果我们执行了一个expandtemplates操作,它应该是response['expandtemplates']。因为我们执行了两个页面,所以这里有两个页面——注意,每个部分的键是页面ID,而不是页面标题。这可能是一种恼人的处理,这意味着当你写代码时,你经常想要做一个for循环,但我们不是在写代码,所以忽略这个(至少现在)。
因此,第一页2632说它的标题是精神分析,它在精神分析(本身)以及链接到它的心理学家列表页面。
第二个页面68西格蒙德·弗洛伊德,没有结果(因为我们将查询限制为总共1个内容)。但它也可以有transcludedinlinkshere部分。
花点时间尝试不同的查询。看看你是否能在你的页面中找到一些有趣的东西。
那么,为什么我选择transcludedinlinkshere?好吧,实际上,我有一些示例代码可以向你展示 - 即使我说没有编程!这是我在个人JavaScript中使用的代码(如果要使用的话,请转到Wiki上的Special:MyPage/common.js),在特殊:链入页面报告的顶部显示一个页面的结果总数。。以下是代码:

/* See totals at the top of WLH pages */
$(function() {
    if (mw.config.get('wgCanonicalSpecialPageName') !== 'Whatlinkshere') return;
    var title = $('#mw-whatlinkshere-target').val();
    var ns = $('#namespace').val();
    title = title ? title : mw.config.get('wgTitle').replace('WhatLinksHere/', '');
    var el = document.createElement('div');
    var display = [ 'Total links: ', 'Total transclusions: ', 'Redirects and links to redirects are NOT included!' ];
    $(el).html(display.join('<br>')).insertAfter($('#firstHeading'));
    return new mw.Api().get({
        action : 'query',
        prop : 'linkshere|transcludedin',
        titles : title,
        lhlimit : 'max',
        tilimit : 'max',
        lhnamespace : ns == '' ? '*' : ns,
        tinamespace : ns == '' ? '*' : ns,
        
    }).then(function(data) {
        console.log(data);
        var lh, ti;
        for (p in data.query.pages) {
            var page = data.query.pages[p];
            lh = page.linkshere ? page.linkshere.length : 0;
            ti = page.transcludedin ? page.transcludedin.length : 0;
        }
        display = [
            'Total links: ' + lh,
            'Total transclusions: ' + ti,
            'Redirects and links to redirects are NOT included!'
        ];
        $(el).html(display.join('<br>'));
    });
});

(注意到我前面提到的只有一个项目的for循环吗?)
所以即使你不理解任何代码部分,或者为什么它在return之后用.then或者其他的,只要看一下这一块:

return new mw.Api().get({
    action : 'query',
    prop : 'linkshere|transcludedin',
    titles : title,
    lhlimit : 'max',
    tilimit : 'max',
    lhnamespace : ns == '' ? '*' : ns,
    tinamespace : ns == '' ? '*' : ns,
    
})

你可以看到操作是一个查询,属性是linksheretranscludedin,titles变量得到一些标题,我之前弄清楚了,我想要linkshere(由lhlimit指定)和transcludedin(由tilimit指定)的最大结果,lhnamespacetimamespace都是基于某些东西指定的(搜索“javascript ternary”,如果你想了解语法的话)。这与我们在format=json 显示中指定的参数非常相似!这是理解如何编写代码以获得像这样有趣的小实用程序的一半。


本文翻译自https://river.me/blog/mediawiki-api-without-coding/,并根据个人实际做了适当修改。翻译水平有限,见谅!

最后修改:2023 年 12 月 31 日
如果觉得我的文章对你有用,请随意赞赏