【问题标题】:Troubleshooting automating a file upload自动上传文件的疑难解答
【发布时间】:2017-03-30 04:09:36
【问题描述】:

我正在尝试使用python3 中的requests 模块自动上传文件。我尝试复制的设置(我手动执行)如下:

  1. 我去网站找我的笔记(代码中的SUBMIT_URL)。

  2. 我被重定向到我大学的登录名(代码中的LOGIN_URL)。

  3. 我登录我的帐户(使用我的用户名/密码,从 credentials.py 导入,因为我不想在这里分享)。

  4. 我被重定向回提交网页。它有一个可以拖放文件的区域。我将文件拖到那里,然后提交。

这是整个过程,我已经完成了大部分工作。 我要登录的文件托管服务称为moodle,它并没有真正的API,所以我一直在尝试“手动”进行。我确信登录工作正常,因为login_page_query.content 返回的内容是“您已登录,但我们无法以任何原因重定向您”。 问题似乎出在下面的draft_query 上。

draft_query 试图模仿chrome sends here 的请求,我试图用DRAFT_FILES_PAYLOAD 来做。 sesskeyclient_iditemid 似乎都是以某种方式在服务器端动态生成的,但我能够通过submit_page.content 的正则表达式搜索得到看起来合理的东西。这通常看起来像this(默认情况下,所有这些都在一行上,因此链接本身可能不是最有用的)。

因此,虽然我无法将 sesskey/other 数据与 chrome 进行比较(因为每次加载页面时它似乎都会发生变化),但每次运行 python 时,我都会得到格式相同的内容作为 chrome,看起来很合理。

我遇到的当前错误是draft_querydraft_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+)&amp;")
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 你的意思是来自login_page_query吗? This 是该请求的内容,this 是从该请求返回的标头。我似乎在那里找不到任何对sesskey 的引用。类似的事情发生在第一个s.get(SUBMIT_URL)(意味着没有引用sesskey),内容是this(这似乎只是我学院登录页面的内容,所以我被重定向了),以及标题是here
  • @MartinGreenaway 我重新检查了我所做的所有查询,并在他们的.headers.content 中搜索了sess。唯一包含它们的是submit_page.content(我目前从中获取密钥)和draft_query.content(我要修复的错误消息的来源)。如果不是来自submit_page.content,我应该在哪里尝试找到sesskey
  • 你不应该。您应该与大学的 IT 团队交谈并从数据库中获取会话密钥。

标签: python python-3.x python-requests


【解决方案1】:

尝试将其从 Multipart 编码器更改为简单的字典。

draft_files_payload = {"sesskey":sess_key, "client_id":client_id, "filepath":"/", "itemid":item_id}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-06
    • 2014-08-29
    • 2011-10-27
    • 1970-01-01
    相关资源
    最近更新 更多