Jump to content

API:编辑

From mediawiki.org
This page is a translated version of the page API:Edit and the translation is 100% complete.
MediaWiki版本:
1.13

使用POST 请求编辑某个页面。

API帮助文档

action=edit

(main | edit)
  • This module requires read rights.
  • This module requires write rights.
  • This module only accepts POST requests.
  • Source: MediaWiki
  • License: GPL-2.0-or-later

Create and edit pages.

Specific parameters:
Other general parameters are available.
title

Title of the page to edit. Cannot be used together with pageid.

pageid

Page ID of the page to edit. Cannot be used together with title.

Type: integer
section

Section identifier. 0 for the top section, new for a new section. Often a positive integer, but can also be non-numeric.

sectiontitle

The title for a new section when using section=new.

text

Page content.

summary

Edit summary.

When this parameter is not provided or empty, an edit summary may be generated automatically.

When using section=new and sectiontitle is not provided, the value of this parameter is used for the section title instead, and an edit summary is generated automatically.

tags

Change tags to apply to the revision.

Values (separate with | or alternative): AWB, convenient-discussions
minor

Mark this edit as a minor edit.

Type: boolean (details)
notminor

Do not mark this edit as a minor edit even if the "Mark all edits minor by default" user preference is set.

Type: boolean (details)
bot

Mark this edit as a bot edit.

Type: boolean (details)
baserevid

ID of the base revision, used to detect edit conflicts. May be obtained through action=query&prop=revisions. Self-conflicts cause the edit to fail unless basetimestamp is set.

Type: integer
basetimestamp

Timestamp of the base revision, used to detect edit conflicts. May be obtained through action=query&prop=revisions&rvprop=timestamp. Self-conflicts are ignored.

Type: timestamp (allowed formats)
starttimestamp

Timestamp when the editing process began, used to detect edit conflicts. An appropriate value may be obtained using curtimestamp when beginning the edit process (e.g. when loading the page content to edit).

Type: timestamp (allowed formats)
recreate

Override any errors about the page having been deleted in the meantime.

Type: boolean (details)
createonly

Don't edit the page if it exists already.

Type: boolean (details)
nocreate

Throw an error if the page doesn't exist.

Type: boolean (details)
watch
Deprecated.

Add the page to the current user's watchlist.

Type: boolean (details)
unwatch
Deprecated.

Remove the page from the current user's watchlist.

Type: boolean (details)
watchlist

Unconditionally add or remove the page from the current user's watchlist, use preferences (ignored for bot users) or do not change watch.

One of the following values: nochange, preferences, unwatch, watch
Default: preferences
watchlistexpiry

Watchlist expiry timestamp. Omit this parameter entirely to leave the current expiry unchanged.

Type: expiry (details)
md5

The MD5 hash of the text parameter, or the prependtext and appendtext parameters concatenated. If set, the edit won't be done unless the hash is correct.

prependtext

Add this text to the beginning of the page or section. Overrides text.

appendtext

Add this text to the end of the page or section. Overrides text.

Use section=new to append a new section, rather than this parameter.

undo

Undo this revision. Overrides text, prependtext and appendtext.

Type: integer
The value must be no less than 0.
undoafter

Undo all revisions from undo to this one. If not set, just undo one revision.

Type: integer
The value must be no less than 0.
redirect

Automatically resolve redirects.

Type: boolean (details)
contentformat

Content serialization format used for the input text.

One of the following values: application/json, application/octet-stream, application/unknown, application/x-binary, text/css, text/javascript, text/plain, text/unknown, text/x-wiki, unknown/unknown
contentmodel

Content model of the new content.

One of the following values: GadgetDefinition, Json.JsonConfig, JsonSchema, Map.JsonConfig, MassMessageListContent, NewsletterContent, Scribunto, SecurePoll, Tabular.JsonConfig, css, flow-board, javascript, json, sanitized-css, text, translate-messagebundle, unknown, wikitext
token

A "csrf" token retrieved from action=query&meta=tokens

The token should always be sent as the last parameter, or at least after the text parameter.

This parameter is required.
returnto

Page title. If saving the edit created a temporary account, the API may respond with an URL that the client should visit to complete logging in. If this parameter is provided, the URL will redirect to the given page, instead of the page that was edited.

Type: page title
Accepts non-existent pages.
returntoquery

URL query parameters (with leading ?). If saving the edit created a temporary account, the API may respond with an URL that the client should visit to complete logging in. If this parameter is provided, the URL will redirect to a page with the given query parameters.

Default: (empty)
returntoanchor

URL fragment (with leading #). If saving the edit created a temporary account, the API may respond with an URL that the client should visit to complete logging in. If this parameter is provided, the URL will redirect to a page with the given fragment.

Default: (empty)
captchaword

Answer to the CAPTCHA

captchaid

CAPTCHA ID from previous request


示例

此示例中的示例代码使用Python。 有关示例请见API:Edit/Editing with Ajax ,响应请参阅Ajax

POST请求

编辑,以及任何POST请求实际上都是一个多步骤的过程。

1. 使用API:登录 中描述的方法之一登录。 请注意,虽然此操作需要将其正确地归为编辑者的贡献,但许多Wiki确实允许用户无需注册或登录帐户即可进行编辑。
2. 获取CSRF令牌
3. 发送带有CSRF令牌的POST请求以在页面上执行操作:

下方的“回应”段落显示了最终的POST请求,以在页面上执行操作。 请参阅API:登录 API:令牌 的页面,以获取对先前步骤的中间JSON响应。

另请注意,此页面上查询中的令牌(tokens)是示例值。 实际的令牌对于每个登录会话和跨站请求都是唯一的。 示例中包括它们只是为了演示如何正确格式化查询。

回应

{
    "edit": {
        "result": "Success",
        "pageid": 94542,
        "title": "Wikipedia:Sandbox",
        "contentmodel": "wikitext",
        "oldrevid": 371705,
        "newrevid": 371707,
        "newtimestamp": "2018-12-18T16:59:42Z"
    }
}

示例代码

Python

#!/usr/bin/python3

"""
    edit.py

    MediaWiki API Demos
    Demo of `Edit` module: POST request to edit a page
    MIT license
"""

import requests

S = requests.Session()

URL = "https://test.wikipedia.org/w/api.php"

# Step 1: GET request to fetch login token
PARAMS_0 = {
    "action": "query",
    "meta": "tokens",
    "type": "login",
    "format": "json"
}

R = S.get(url=URL, params=PARAMS_0)
DATA = R.json()

LOGIN_TOKEN = DATA['query']['tokens']['logintoken']

# Step 2: POST request to log in. Use of main account for login is not
# supported. Obtain credentials via Special:BotPasswords
# (https://www.mediawiki.org/wiki/Special:BotPasswords) for lgname & lgpassword
PARAMS_1 = {
    "action": "login",
    "lgname": "bot_user_name",
    "lgpassword": "bot_password",
    "lgtoken": LOGIN_TOKEN,
    "format": "json"
}

R = S.post(URL, data=PARAMS_1)

# Step 3: GET request to fetch CSRF token
PARAMS_2 = {
    "action": "query",
    "meta": "tokens",
    "format": "json"
}

R = S.get(url=URL, params=PARAMS_2)
DATA = R.json()

CSRF_TOKEN = DATA['query']['tokens']['csrftoken']

# Step 4: POST request to edit a page
PARAMS_3 = {
    "action": "edit",
    "title": "Project:Sandbox",
    "token": CSRF_TOKEN,
    "format": "json",
    "appendtext": "Hello"
}

R = S.post(URL, data=PARAMS_3)
DATA = R.json()

print(DATA)

PHP

<?php

/*
    edit.php

    MediaWiki API Demos
    Demo of `Edit` module: POST request to edit a page
    MIT license
*/

$endPoint = "https://test.wikipedia.org/w/api.php";

$login_Token = getLoginToken(); // Step 1
loginRequest( $login_Token ); // Step 2
$csrf_Token = getCSRFToken(); // Step 3
editRequest($csrf_Token); // Step 4

// Step 1: GET request to fetch login token
function getLoginToken() {
	global $endPoint;

	$params1 = [
		"action" => "query",
		"meta" => "tokens",
		"type" => "login",
		"format" => "json"
	];

	$url = $endPoint . "?" . http_build_query( $params1 );

	$ch = curl_init( $url );
	curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
	curl_setopt( $ch, CURLOPT_COOKIEJAR, "cookie.txt" );
	curl_setopt( $ch, CURLOPT_COOKIEFILE, "cookie.txt" );

	$output = curl_exec( $ch );
	curl_close( $ch );

	$result = json_decode( $output, true );
	return $result["query"]["tokens"]["logintoken"];
}

// Step 2: POST request to log in. Use of main account for login is not
// supported. Obtain credentials via Special:BotPasswords
// (https://www.mediawiki.org/wiki/Special:BotPasswords) for lgname & lgpassword
function loginRequest( $logintoken ) {
	global $endPoint;

	$params2 = [
		"action" => "login",
		"lgname" => "bot_user_name",
		"lgpassword" => "bot_password",
		"lgtoken" => $logintoken,
		"format" => "json"
	];

	$ch = curl_init();

	curl_setopt( $ch, CURLOPT_URL, $endPoint );
	curl_setopt( $ch, CURLOPT_POST, true );
	curl_setopt( $ch, CURLOPT_POSTFIELDS, http_build_query( $params2 ) );
	curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
	curl_setopt( $ch, CURLOPT_COOKIEJAR, "cookie.txt" );
	curl_setopt( $ch, CURLOPT_COOKIEFILE, "cookie.txt" );

	$output = curl_exec( $ch );
	curl_close( $ch );

}

// Step 3: GET request to fetch CSRF token
function getCSRFToken() {
	global $endPoint;

	$params3 = [
		"action" => "query",
		"meta" => "tokens",
		"format" => "json"
	];

	$url = $endPoint . "?" . http_build_query( $params3 );

	$ch = curl_init( $url );

	curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
	curl_setopt( $ch, CURLOPT_COOKIEJAR, "cookie.txt" );
	curl_setopt( $ch, CURLOPT_COOKIEFILE, "cookie.txt" );

	$output = curl_exec( $ch );
	curl_close( $ch );

	$result = json_decode( $output, true );
	return $result["query"]["tokens"]["csrftoken"];
}

// Step 4: POST request to edit a page
function editRequest( $csrftoken ) {
	global $endPoint;

	$params4 = [
		"action" => "edit",
		"title" => "Project:Sandbox",
		"appendtext" => "Hello",
		"token" => $csrftoken,
		"format" => "json"
	];

	$ch = curl_init();

	curl_setopt( $ch, CURLOPT_URL, $endPoint );
	curl_setopt( $ch, CURLOPT_POST, true );
	curl_setopt( $ch, CURLOPT_POSTFIELDS, http_build_query( $params4 ) );
	curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
	curl_setopt( $ch, CURLOPT_COOKIEJAR, "cookie.txt" );
	curl_setopt( $ch, CURLOPT_COOKIEFILE, "cookie.txt" );

	$output = curl_exec( $ch );
	curl_close( $ch );

	echo ( $output );
}

JavaScript

/*  
    edit.js
 
    MediaWiki API Demos
    Demo of `Edit` module: POST request to edit a page

    MIT license
*/

var request = require('request').defaults({jar: true}),
    url = "https://test.wikipedia.org/w/api.php";

// Step 1: GET request to fetch login token
function getLoginToken() {
    var params_0 = {
        action: "query",
        meta: "tokens",
        type: "login",
        format: "json"
    };

    request.get({ url: url, qs: params_0 }, function (error, res, body) {
        if (error) {
            return;
        }
        var data = JSON.parse(body);
        loginRequest(data.query.tokens.logintoken);
    });
}

// Step 2: POST request to log in. 
// Use of main account for login is not
// supported. Obtain credentials via Special:BotPasswords
// (https://www.mediawiki.org/wiki/Special:BotPasswords) for lgname & lgpassword
function loginRequest(login_token) {
    var params_1 = {
        action: "login",
        lgname: "bot_username",
        lgpassword: "bot_password",
        lgtoken: login_token,
        format: "json"
    };

    request.post({ url: url, form: params_1 }, function (error, res, body) {
        if (error) {
            return;
        }
        getCsrfToken();
    });
}

// Step 3: GET request to fetch CSRF token
function getCsrfToken() {
    var params_2 = {
        action: "query",
        meta: "tokens",
        format: "json"
    };

    request.get({ url: url, qs: params_2 }, function(error, res, body) {
        if (error) {
            return;
        }
        var data = JSON.parse(body);
        editRequest(data.query.tokens.csrftoken);
    });
}

// Step 4: POST request to edit a page
function editRequest(csrf_token) {
    var params_3 = {
        action: "edit",
        title: "Project:Sandbox",
        appendtext: "test edit",
        token: csrf_token,
        format: "json"
    };

    request.post({ url: url, form: params_3 }, function (error, res, body) {
        if (error) {
            return;
        }
        console.log(body);
    });
}

// Start From Step 1
getLoginToken();

MediaWiki JS

/*
	edit.js

	MediaWiki API Demos
	Demo of `Edit` module: POST request to edit a page

	MIT License
*/

var params = {
		action: 'edit',
		title: 'Project:Sandbox',
		appendtext: 'Hello',
		format: 'json'
	},
	api = new mw.Api();

api.postWithToken( 'csrf', params ).done( function ( data ) {
	console.log( data );
} );

使用示例

编辑冲突

Python示例”是一个对于注册用户编辑请求的简单实现。 在实际情况下,应注意防止编辑冲突。 当两个或多个用户试图同时编辑同一页面时,可能会发生这种情况。

当我们请求CSRF令牌时,可以通过检索最后编辑版本 的时间戳来避免冲突。 在第3步的CSRF令牌请求中加入prop=info|revisions可以获取最新版本的时间戳。 当我们发出编辑请求时,此时间戳将用作basetimestamp

此外还需要开始编辑的准确时间。 同样可以通过在CSRF请求中添加curtimestamp来检索此内容。 该值将作为starttimestamp

最后,在实际的编辑请求中,将basetimestampstarttimestamp参数设定为类似如下内容:

大编辑

包含了大量的文本内容(超过8000个字符)的POST请求应该在请求头中加入Content-Type: multipart/form-data。 由于multipart/form-data无需对空格和标点进行HTML字符转义(例如,百分比编码),传输的数据量将会比使用百分比编码的相同内容数据更小。

但是,multipart/form-data仍然会增加一些开销——每个参数大约160个字节。 对于不需要添加许多转义符的短消息,此开销量可能是低效的,因此百分比编码是这一情况的首选。[1]

请注意对于上文的Python示例代码,该请求默认使用百分比编码。

请参见MDN Web 文档来获取有关内容类型(content-type)和POST请求的更多技术讨论。 请参见Python Requests文档来获取如何使用与Python示例代码类似的方法来传递multipart/form-data

验证码

如果您的目标wiki使用验证码 ,您的请求可能会返回一个错误值,该值包含了一个id编号和简单的测验,例如一个问题、一道数学题或是一张图片的URL。 为了完成您的编辑,您必须完成这一测验,然后将id和正确的答案附在原始的请求字符串后并再次发送请求,例如: captchaid=sampleId&captchaword=answer

其他验证码系统和插件可能会使用类似的不同参数。 通常情况下,将id和测试题的字段名称用作第二个请求中的参数。

可能的错误

代码 信息
notitle title参数必须被设置。
missingparam 需要text、​appendtext和undo中的至少一个参数。
notoken token参数必须被设置。
invalidsection section参数必须为有效的章节ID或new
protectedpage 此页面已受到保护,以防止编辑或其他操作。
cantcreate 您没有权限创建新页面。
cantcreate-anon 匿名用户无法创建新页面
articleexists 您尝试创建的页面已经被创建。
noimageredirect-anon 匿名用户不能创建图片重定向。
noimageredirect 您没有权限创建图片重定向。
spamdetected 您的编辑被拒绝,因为它包含垃圾部分:Wikitext
abusefilter-warning 此操作已被自动识别为有害。
abusefilter-disallowed 此操作已被自动识别为有害,并已不被允许。
contenttoobig 您提供的内容超过了bytes千字节的页面大小限制。
Where bytes is the value of $wgMaxArticleSize .
noedit-anon 匿名用户不能编辑页面。
noedit 您没有权限编辑页面。
pagedeleted 在您取得页面时间戳以来,页面已被删除。
emptypage 不允许创建新的、空的页面。
emptynewsection 无法创建空的新章节。
editconflict 编辑冲突。
revwrongpage rrevid不是pagename的修订版本。
如果undoundoafterrevid(版本id)有误将会抛出此错误
undofailure 因存在冲突的中间编辑,本编辑不能撤销。
missingtitle 您指定的页面不存在。
(参见上文nocreate参数
mustbeposted edit模块需要POST请求。
readapidenied 您需要读取权限以使用此模块。
writeapidenied 您不被允许通过API编辑此wiki。
noapiwrite 通过API编辑此wiki已禁用。
badtoken 无效的CSRF令牌。
missingparam title, pageid参数必须被设置。
invalidparammix 参数title, pageid不能一起使用。
invalidtitle 错误标题“title”。
invalid-content-data 无效的内容数据
尝试编辑包含不合规数据的JSON页面或尝试编辑MassMessageListContent页面时发生
nosuchpageid 没有ID为pageid的页面。
pagecannotexist 命名空间不允许实际页面。
nosuchrevid 没有ID为undo的修订版本。
nosuchrevid 没有ID为undoafter的修订版本。
badmd5 提供的MD5哈希不正确。
hookaborted 您尝试的修改被扩展程序中止。
parseerror 内容序列化失败:parseerror
summaryrequired ⧼apierror-summaryrequired⧽
blocked 您已被封禁,不能编辑。
ratelimited 您已超过您的速率限制。请等待一段时间再试。
unknownerror 未知错误:“retval”。
nosuchsection 没有章节$1。
sectionsnotsupported 内容模型$1不支持章节。
editnotsupported 不支持使用基于文字的编辑API编辑此类型页面。
appendnotsupported 不能使用内容模型$1附加在页面上。
redirect-appendonly 您试图使用重定向跟随模式编辑,而这必须与section=newprependtextappendtext共同使用。
edit-invalidredirect 跟随重定向时无法编辑$1,因为目标$2无效。
badformat 由$3使用的内容模型$2尚不支持请求的内容格式$1。
customcssprotected 您没有权限编辑此CSS页面,因为此页面包含另一位用户的个人设置。
customjsprotected 您没有权限编辑此JavaScript页面,因为此页面包含另一位用户的个人设置。
taggingnotallowed 您无权应用标签
badtags 标签“Tag”不允许手动应用。
以下标签不允许手动应用:Tag1、​ Tag2
tpt-target-page 本页面无法手动更新。本页面是$1页面的翻译版,可以使用[$2 翻译工具]来更新该翻译。
如果使用了Extension:翻译 ,那么不允许编辑被翻译的子页面。

参数历史

  • v1.35: 启用baserevid
  • v1.25: 启用tags
  • v1.21: 启用contentformat, contentmodel
  • v1.20: 启用pageid
  • v1.19: 启用sectiontitle
  • v1.18: 弃用captchaid, captchaword
  • v1.17: 启用redirect
  • v1.16: 弃用watch, unwatch
  • v1.16: 启用watchlist
  • v1.15: 启用undo, undoafter
  • v1.14: 启用starttimestamp

更多注释

  • API并不严格需要登录,但登录操作可以正确地标记作者的贡献。 未登录用户的成功编辑将以IP地址作为贡献者。
  • 未登录的机器人可能会面临编辑和其他写入请求的限制;有关更多详细信息,请参见创建机器人#登录
  • 未登录的用户将始终获得空的CSRF令牌+\
  • 请求令牌的过程在各个版本中已多次更改。 参见API:令牌 以获取更多信息。
  • ResourceLoader 提供了一种在Wiki页面中运行代码时获取编辑令牌的方法。
  • 在单个登录会话期间,您可以对同一Wiki中的所有编辑操作使用相同的CSRF令牌。
  • 优良作法是在查询字符串的末尾,或至少在text参数之后传递请求中的所有令牌。 这样,如果连接中断,令牌将不会被传递,因此编辑将失败。 如果您使用了mw.Api 来发送请求,那么这一操作会自动进行。
  • 尽管从1.18版本开始,captchaidcaptchaword已经在技术上从API:Edit中移除,但Extension:ConfirmEdit 扩展了API:Edit以便与验证码一起使用。 因此,如果安装了ConfirmEdit插件,这些参数仍然可用。 在1.18及以后版本的MediaWiki中附带了ConfirmEdit。

參見


參考資料