首页 > 解决方案 > 如何使用 python 请求在没有 POST 的情况下传输表单数据?

问题描述

我正在编写一小段 python 代码来登录我的几个“投资”网站并获取当前投资的金额。我正在使用 pythons requests 库并分析 html-source 以识别要填写的表单和字段。

因此,表单可能如下所示:

<form class="onboarding-form" id="loginForm" action="https://estateguru.co/portal/login/authenticate" method="post" data-redirect="https://estateguru.co/portal/home">
    <div class="row">
        <div class="col-md-6">
            <div class="form-group">
                <input type="text" class="form-control main-input" name="username">
                <label class="bmd-label-floating main-label">E-Mail</label>
                <em id="username-error" class="error bmd-help help-block" style="display:none;">This field is required.</em>
            </div>
        </div>

        <div class="col-md-6">
            <div class="form-group">
                <input type="password" class="form-control main-input login-pass" name="password">
                <label class="bmd-label-floating main-label long-label">Passwort (Mindestens 8 Zeichen)</label>
                <em id="password-error" class="error bmd-help help-block" style="display:none;">This field is required.</em>
                <a href="#" class="show-pass-icon"><i class="zmdi zmdi-eye"></i></a>
            </div>
        </div>
    </div>

在这种情况下,我的代码如下所示:

import requests
_username = 'xxx'
_password = 'yyy'

loginUrl = 'https://estateguru.co/portal/login/authenticate'
readUrl = 'https://estateguru.co/portal/portfolio/overview'
with requests.session() as s:
    
    payload = {"username": _username, "password": _password}

    final = s.post(loginUrl, data = payload)
    result = s.get(readUrl)
    print(result)

这对许多网站来说就像一个魅力!但是现在我得到了一个表单中没有“method=post”的网站,所以我不知道如何传输表单数据。html 部分(来自http://www.reinvest24.com/en/login)如下所示:

<form>
    <div class="form-group">
        <input type="text" id="email" placeholder="Email" value="" name="email" maxLength="100" class="form-control"/>
    </div>
    <div class="form-group">
        <input type="password" id="password" placeholder="Password" value="" name="password" maxLength="100" class="form-control"/>
    </div>
    <p class="forgot text-right">
        <a href="/en/forgot-password"><span>Forgot password?</span></a>
    </p>
    <input type="submit" class="btn btn-success" value="Login"/>
        <p class="reg text-center">
            <span>Don&#x27;t have an account?</span>
             <a href="/en/registration">
            <span>Sign up</span></a>
        </p>
</form>

所以在没有明确方法的情况下,我尝试了

final = s.get(loginUrl, data = payload)

但没有成功。两种情况下的结果都是一个 html 输出,上面写着“正在加载授权详细信息......”。

所以我的问题是:我缺少正确的方法(POST/GET)来传输数据还是缺少其他参数?有些网站需要一个会话令牌,我从登录站点本身检索它(就像https://www.mintos.com/de/login中的情况一样),但在我看来,这不是问题所在。

标签: pythonhtmlformspython-requests

解决方案


默认情况下,当方法设置为 GET 时,会忽略 HTTP 请求的正文(表单数据)。因此,您不应尝试通过 GET 提交请求(通过 GET 传输敏感信息不仅不安全,服务器只会忽略您请求的用户名/密码)。

这里的问题是该页面正在执行一些 JavaScript 魔术以通过不同的 URL 提交您的请求。每当您尝试登录该网站时,请打开您的网络检查器并查看“网络”选项卡。您应该会看到请求被发布到https://api-frontend.reinvest24.com/graphql.

当我们检查这个 POST 请求时,我们可以看到数据是作为 JSON 正文而不是表单正文传输的。所以你的请求应该看起来像这样:

login_url = 'https://api-frontend.reinvest24.com/graphql'
payload = {
    "operationName": "login",
    "variables": {
        "email": EMAIL,
        "password": PASSWORD
    },
    "query": "mutation login($email: String!, $password: String!) {\n  login(email: $email, password: $password)\n}\n"
}
r = s.post(url=login_url, json=payload)

# note that we used the 'json' parameter here not 'data'

Chrome 网络检查器是您在这里观察登录时如何传输数据的朋友。

祝你好运!


推荐阅读