如果网站不让我登录,如何 requests.Session().get?

How to requests.Session().get if website does not keep me logged in?

我正在尝试完成需要先登录的页面的网络抓取。我相当确定我的代码和输入名称('login' 和 'password')是正确的,但它仍然给我一个 'Login Failed' 页面。这是我的代码:

payload = {'login': 'MY_USERNAME', 'password': 'MY_PASSWORD'}
login_url = "https://www.spatialgroup.com.au/property_daily/"

with requests.Session() as session:

    session.post(login_url, data=payload)
    response = session.get("https://www.spatialgroup.com.au/cgi-bin/login.cgi")
    html = response.text

print(html)

我四处窥探了一下,发现当我 运行 我的 session.get("LOGGEDIN_PAGE") 时会话不会保持登录状态。例如,如果我完成登录过程,然后在地址栏中输入 URL,我知道这是一个只有登录后才能访问的页面,它 returns 我到 'Login Failed' 页。如果我的登录会话没有维护,我该如何解决这个问题?

如果没有您正在使用的实际网站,很难为您提供帮助。话虽如此,我建议您更改此行:

session.post(login_url, data=payload)

给这个:

session.post(login_url, json=payload)

希望这对您有所帮助

正如其他人所提到的,如果不知道您尝试登录的实际站点,很难在这里提供帮助。

我要指出的是,您根本没有使用任何 set HTTP headers,这是对网页登录的常见验证检查。如果您确定您以正确的格式发布数据(形式编码与 json 编码),那么我会打开 Chrome 检查器并从您的浏览器复制 user-agent。

s = requests.Session()
s.headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36',
    'Accept': '*/*'
}

此外,最好检查您使用 try/except 模式发出的每个 Web 请求的响应状态代码。这将帮助您在编写和测试请求时捕获错误,而不是盲目猜测哪些请求是错误的。

r = requests.get('http://mypage.com')
try:
    r.raise_for_status()
except requests.exceptions.HTTPError:
    print('oops bad status code {} on request!'.format(r.status_code))

编辑: 现在您已经向我们提供了网站,检查登录尝试会发现表单数据实际上并未发布到该网站,而是正在发送到 CGI 脚本 url.

要找到它,请打开 Chrome Inspector 并在尝试登录时查看 "Network" 选项卡。您会看到登录实际上被发送到 https://www.spatialgroup.com.au/cgi-bin/login.cgi,而不是实际的登录页面。当你提交到这个登录页面时,它会在登录后执行一个302重定向。我们可以在执行请求后检查location是否登录成功。

知道这一点我会发送这样的请求:

s = requests.Session()

# try to login
r = s.post(
    url='https://www.spatialgroup.com.au/cgi-bin/login.cgi',
    headers={
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3'
    },
    data={
        'login': USERNAME,
        'password': PASSWORD
    }
)

# now lets check to make sure we didnt get 4XX or 5XX errors
try:
    r.raise_for_status()
except requests.exceptions.HTTPError:
    print('oops bad status code {} on request!'.format(r.status_code))
else:
    print('our login redirected to: {}'.format(r.url))

# subsequently if the login was successful, you can now make a request to the login-protected page at this point