【发布时间】:2017-03-30 04:09:36
【问题描述】:
我正在尝试使用python3 中的requests 模块自动上传文件。我尝试复制的设置(我手动执行)如下:
我去网站找我的笔记(代码中的
SUBMIT_URL)。我被重定向到我大学的登录名(代码中的
LOGIN_URL)。我登录我的帐户(使用我的用户名/密码,从
credentials.py导入,因为我不想在这里分享)。我被重定向回提交网页。它有一个可以拖放文件的区域。我将文件拖到那里,然后提交。
这是整个过程,我已经完成了大部分工作。
我要登录的文件托管服务称为moodle,它并没有真正的API,所以我一直在尝试“手动”进行。我确信登录工作正常,因为login_page_query.content 返回的内容是“您已登录,但我们无法以任何原因重定向您”。
问题似乎出在下面的draft_query 上。
draft_query 试图模仿chrome sends here 的请求,我试图用DRAFT_FILES_PAYLOAD 来做。 sesskey、client_id 和 itemid 似乎都是以某种方式在服务器端动态生成的,但我能够通过submit_page.content 的正则表达式搜索得到看起来合理的东西。这通常看起来像this(默认情况下,所有这些都在一行上,因此链接本身可能不是最有用的)。
因此,虽然我无法将 sesskey/other 数据与 chrome 进行比较(因为每次加载页面时它似乎都会发生变化),但每次运行 python 时,我都会得到格式相同的内容作为 chrome,看起来很合理。
我遇到的当前错误是draft_query。 draft_query.content是
b'{"error":"A required parameter (sesskey) was missing","errorcode":"missingparam","stacktrace":null,"debuginfo":null,"reproductionlink":null}'
即使draft_files_payload 是
<MultipartEncoder: (('sesskey', 'X6DD4DCAHC'), ('client_id', '58dc838805c18'), ('filepath', '/'), ('itemid', '288033100'))>
其中明显包括sesskey。作为旁注,我曾经将draft_files_payload 用作字典,但我担心顺序可能很重要。但这根本没有帮助。
另外值得注意的是,对于我正在尝试模拟的 Chrome 查询(使用 draft_files_query),Content-Type 是
application/x-www-form-urlencoded; charset=UTF-8
requests 默认为text/plain,因此我尝试将其设置为标题。我不知道它是否有效/是否产生了积极影响。
我不确定任何人可以如何具体地帮助我,因为我无法真正透露进行此动手操作所需的凭据。任何人都可以建议我可以做的一般策略/故障排除吗?我真的对自己在做什么一无所知,昨天通过广泛的帮助得到了很大的帮助(尽管现在我对我觉得可以复制下面的东西感到很舒服)。
总结一下:
当前错误:
draft_query 无法成功复制 this 查询,即使我的数据/格式似乎正确。
import requests
from requests_toolbelt.multipart.encoder import MultipartEncoder
import http.client
from credentials import CREDENTIALS
import re
http.client.HTTPConnection._http_vsn_str = 'HTTP/1.0'
# Regex patterns here
SESS_KEY_RE = re.compile(r"\"sesskey\":\"(\w*)\"")
ITEM_ID_RE = re.compile(r"\"itemid\":(\d*),")
AUTHOR_RE = re.compile(r"\"author\":\"([^\"]+)\"")
CTX_RE = re.compile(r";ctx_id=(\d+)&")
CLIENT_ID_RE = re.compile(r"\"client_id\":\"(\w*)\"")
##
LOGIN_URL = 'https://weblogin.reed.edu/'
SUBMIT_URL = 'https://moodle.reed.edu/mod/data/edit.php?d=485'
DRAFT_FILES_URL = 'https://moodle.reed.edu/repository/draftfiles_ajax.php?action=list'
UPLOAD_URL = 'https://moodle.reed.edu/repository/repository_ajax.php?action=upload'
TITLE = r"MATH 389 3-20-17.pdf"
FILENAME = r"/home/mark/classes/moodle-notetaking-uploader/MATH 389 3-20-17.pdf"
# repo_id 4 seems to correspond with "upload a file", look at "sortorder":4
with open(FILENAME, 'rb') as f:
s = requests.Session()
s.get(SUBMIT_URL)
# Removing above breaks this, not sure why
login_page_query = s.post(LOGIN_URL, data=CREDENTIALS)
submit_page = s.get(SUBMIT_URL)
text = l.content.decode()
sess_key = SESS_KEY_RE.search(text).group(1)
item_id = ITEM_ID_RE.search(text).group(1)
author = AUTHOR_RE.search(text).group(1)
ctx_id = CTX_RE.search(text).group(1)
client_id = CLIENT_ID_RE.search(text).group(1)
draft_header = {'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'}
draft_files_payload = MultipartEncoder(fields = (("sesskey", sess_key), ("client_id", client_id),
("filepath", "/"), ("itemid", item_id)))
file_payload = {"file": ("repo_upload_file", f, "application/pdf")}
data_payload = {"sesskey": sess_key, "repo_id": "4", "itemid": item_id,
"author": author, "savepath": "/", "title": TITLE,
"ctx_id": ctx_id}
draft_query = s.post(DRAFT_FILES_URL, data=draft_files_payload,headers = draft_header)
file_query = s.post(UPLOAD_URL, files=file_payload, data=data_payload)
【问题讨论】:
-
这是一个 Moodle 错误。您的“sesskey”需要与您登录 Moodle 时创建的会话密钥相同。
-
@MartinGreenaway 我重新检查了我所做的所有查询,并在他们的
.headers和.content中搜索了sess。唯一包含它们的是submit_page.content(我目前从中获取密钥)和draft_query.content(我要修复的错误消息的来源)。如果不是来自submit_page.content,我应该在哪里尝试找到sesskey? -
你不应该。您应该与大学的 IT 团队交谈并从数据库中获取会话密钥。
标签: python python-3.x python-requests