使用Requests模块的Python 3脚本登录网站

4

我正在尝试使用Requests模块编写一些Python(3.3.2)代码,以便登录网站。以下是登录页面的表单部分:

<form method="post" action="https://www.ibvpn.com/billing/dologin.php" name="frmlogin">
<input type="hidden" name="token" value="236647d2da7c8408ceb78178ba03876ea1f2b687" />

<div class="logincontainer">

    <fieldset>

        <div class="clearfix">
            <label for="username">Email Address:</label>
            <div class="input">
                <input class="xlarge" name="username" id="username" type="text" />
            </div>
        </div>

        <div class="clearfix">
            <label for="password">Password:</label>
            <div class="input">
                <input class="xlarge" name="password" id="password" type="password"/>
            </div>
        </div>

        <div align="center">

          <p>
                <input type="checkbox" name="rememberme" /> Remember Me
            </p>

          <p><a href="pwreset.php">Request a Password Reset</a></p>
        </div>

    </fieldset>

</div>

<div class="actions">
<input type="submit" class="btn primary" value="Login" />
</div>

</form>

这是我的代码,试图处理隐藏的输入:

import requests
from bs4 import BeautifulSoup

url = 'https://www.ibvpn.com/billing/clientarea.php'

body = {'username':'my email address','password':'my password'}

s = requests.Session()

loginPage = s.get(url)

soup = BeautifulSoup(loginPage.text)

hiddenInputs = soup.findAll(name = 'input', type = 'hidden')

for hidden in hiddenInputs:
    name = hidden['name']
    value = hidden['value']
    body[name] = value

r = s.post(url, data = body)

这只返回登录页面。如果我将我的登录数据发布到“action”字段中的URL,我会收到404错误。

我在StackExchange上看到过其他帖子,自动cookie处理似乎不起作用,因此我也尝试手动处理cookie:

cookies = dict(loginPage.cookies)

r = s.post(url, data = body, cookies = cookies)

但是这只会返回登录页面。

我不知道这是否与问题有关,但在运行上面的任何代码变体后,输入r.cookies会返回<<class 'requests.cookies.RequestsCookieJar'>[]>

如果有人有任何建议,我很愿意听取。


你能否把你完成的代码发表为答案(如果你还有的话)?我会觉得很有帮助。 - Magwich
嗨@Magwich,除了我在头部添加了User-Agent之外,其他都和上面一样:s.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36'并按答案中建议的将其发布到“action”URL:s.post(soup.form['action'], data = body, headers = {'Referer':'http://www.ibvpn.com/index/'}) - Tom Harrop
1个回答

5
你正在加载错误的URL。该表单具有一个action属性:
<form method="post" action="https://www.ibvpn.com/billing/dologin.php" name="frmlogin">

所以你必须将登录信息发布到以下位置:

https://www.ibvpn.com/billing/dologin.php

不要将页面回传到登录页面,而是将POST请求发送到soup.form['action']

r = s.post(soup.form['action'], data=body)

您的代码已经很好地处理了cookies; 比如,我可以看到在请求登录表单后s.cookies保存了一个cookie。

如果仍然无法工作(返回404错误),那么服务器可能使用其他技术来检测脚本与真实浏览器。通常是通过解析请求头来完成的。查看您的浏览器标头并复制它们。他们可能只是解析User-Agent头,但Accept-*头和Referrer也可能起作用。


嗨Martijn,非常感谢您的快速回复。发布到该URL返回404错误。 - Tom Harrop
@Tom:很可能他们正在使用更多的技巧来检测真实的浏览器。调整报头以匹配您的浏览器(通常是用户代理,但可能需要其他报头)。 - Martijn Pieters
@Tom:然而,向“clientarea.php” URL发布是肯定不正确的登录方式,特别是当表单有一个明确的“action”属性应该被尊重时。 - Martijn Pieters
嘿,搞定了。添加了s.headers['Referer'] = 'http://www.ibvpn.com/index/'(并发布到动作属性指定的URL),现在我得到了正确的页面。非常感谢。 - Tom Harrop
你几乎肯定不想在会话中使用'Referer'头。会话头是用于每个请求的头(例如User-Agent)的头,每个请求的头是适用于单个请求的头(例如Referer)。 - Lukasa
@Lukasa:好的。我在s.post命令中添加了headers = {'Referer':'http://www.ibvpn.com/index/'},现在它可以正常工作了。谢谢。 - Tom Harrop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接