使用 Python 将文件上传到最新的 MediaWiki 实例的最简单方法?
Simplest way to upload a file to an up to date MediaWiki instance with Python?
最近我遇到了一些问题和文章,非常简要地介绍了使用 urllib
、requests
、mwapi
、poster
和各种其他工具来要么执行 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)
最近我遇到了一些问题和文章,非常简要地介绍了使用 urllib
、requests
、mwapi
、poster
和各种其他工具来要么执行 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)