使用 Python 将文件上传到最新的 MediaWiki 实例的最简单方法?

Simplest way to upload a file to an up to date MediaWiki instance with Python?

最近我遇到了一些问题和文章,非常简要地介绍了使用 urllibrequestsmwapiposter 和各种其他工具来要么执行 HTTP POST,要么使用 API 将一个或多个文件上传到 MediaWiki 实例。到目前为止,没有任何效果。

那么,有人可以提供一个简单的代码块来可靠地将文件上传到这样的 Wiki 吗?我的偏好是 Requests and/or Python 3,但在这一点上我非常绝望并且对几乎任何事情都持开放态度。

编辑: 根据评论中的要求,下面是我尝试的最后一段代码。它没有错误地完成,但当然没有文件上传或对 Wiki 日志进行任何更改。

from urllib.parse import quote
import requests

user = 'username'
passw = quote('password')

baseurl = 'http://127.0.0.1:8020/mediawiki/'
apiurl = baseurl + 'api.php'
login_params = '?action=login&lgname=%s&lgpassword=%s&format=json'% (user, passw)

# Login request
r1 = requests.post(apiurl+login_params)
login_token = r1.json()['login']['token']

# Login confirm
login_params2 = login_params+'&lgtoken=%s'% login_token
r2 = requests.post(apiurl+login_params2, cookies=r1.cookies)

# Get edit token
params3 = '?format=json&action=query&meta=tokens&continue='
r3 = requests.get(apiurl+params3, cookies=r2.cookies)
edit_token = r3.json()['query']['tokens']['csrftoken']

edit_cookie = r2.cookies.copy()
edit_cookie.update(r3.cookies)

# Upload file
with open('91.png', 'rb') as f:
    headers = {'content-type': 'multipart/form-data'}
    payload = {'action': 'upload', 'filename': 'Image', 'file': '91.png', 'token': edit_token}
    files = {'files': f}
    r4 = requests.post(apiurl, headers=headers, data=payload, files=files, cookies=edit_cookie)

对我来说,你最后的代码没有错误似乎很奇怪。假设您使用标准配置设置 MediaWiki,api.php 在 baseurl/w/api.php 中,而不是 baseurl/api.php。这意味着您一直请求错误的页面。再试一次,但这次将 apiurl = baseurl + 'api.php' 替换为 apiurl = baseurl + 'w/api.php'

原来我没试过的那个成功了。使用 mwclient 的文档示例,上传成功。

很高兴您 mwclient 开始工作,但我想我可以回答您对仅使用 Python 3 和 requests 的偏好。

我在做同样的事情时非常头疼,终于让下面的工作开始了。我也在 https://www.mediawiki.org/wiki/API_talk:Upload#Python_with_requests 上发布了它,但由于这是我在尝试解决问题时发现的问题,我将在下面重现...

严格来说,您可能不需要 BotPassword,但这是个好主意。

import requests

api_url = 'https://project/w/api.php'

USER,PASS=u'BotUsername@Instancename',u'[[Special:BotPasswords]] password' 
#Ensure bot instance is permissioned for createeditmovepage, uploadfile, uploadeditmovefile

FILENAME='/path/to/file'
REMOTENAME='remote_filename.ext'
USER_AGENT='Descriptive User Agent per [[:meta:User-Agent_policy]]'


# get login token and log in
payload = {'action': 'query', 'format': 'json', 'utf8': '', 
           'meta': 'tokens', 'type': 'login'}

r1 = requests.post(api_url, data=payload)
login_token=r1.json()['query']['tokens']['logintoken']

login_payload = {'action': 'login', 'format': 'json', 'utf8': '', 
           'lgname': USER, 'lgpassword': PASS, 'lgtoken': login_token}

r2 = requests.post(api_url, data=login_payload, cookies=r1.cookies)
cookies=r2.cookies.copy()

# We have now logged in and can request edit tokens thusly:

def get_edit_token(cookies):
        edit_token_response=requests.post(api_url, data={'action': 'query',
                                                    'format': 'json', 
                                                    'meta': 'tokens'}, cookies=cookies)
        return edit_token_response.json()['query']['tokens']['csrftoken']

# Now actually perform the upload:

upload_payload={'action': 'upload', 
            'format':'json',
            'filename':REMOTENAME, 
            'comment':'<MY UPLOAD COMMENT>',
            'text':'Text on the File: page... description, license, etc.',
            'token':get_edit_token(cookies)}

files={'file': (REMOTENAME, open(FILENAME,'rb'))}

headers={'User-Agent': USER_AGENT}

upload_response=requests.post(api_url, data=upload_payload,files=files,cookies=cookies,headers=headers)