requests库登录网站,Session()和session()差一个大小写非常要命

笔者最近用Python爬取网站,首页需要输入用户名和密码,由于该网站不需要验证码,登录步骤比较简单。用selenium的webdriver打开Chrome浏览器实现自动化来登录,代码不难写而且登录很顺利。后来再想,selenium打开浏览器比较慢,占用内存比较多,既然我要爬取的网站不需要验证码之类的繁琐验证,那么只用requests库来登录网站行不行呢?

先分析该网站首页的源代码,了解到登录网站需要post动作,需要一些表单数据,如用户名、密码等,其中还要一个hash值,这个hash值每次刷新网页都不同,因此在网页源代码中用re库的re.search()获取。然后用urlencode()把登录用的表单数据编译成url,再来post。

import requests
from urllib.parse import urlencode

headers={'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36'}

res=requests.get('https://。。。。。。.com',headers=headers)
if res.status_code==200:
    res=res.text
else:
    print('打开网页失败。')
    exit()

# 查找网页源代码中的hash值
try:
    hash_value=re.search('name="hash" value="(.*?)"',res)[1]
except Exception:
    print('找不到hash值')
    exit()

# 登录用的表单数据
data={'username':'这里填你的用户名',
      'password':'你的密码',
      'hash': hash_value,
      }

# 用urlencode把登录表单数据编译成url
posturl='https://。。。。。。.com/login?'+urlencode(data)

res=requests.post(posturl,headers=headers,timeout=10)

if res.status_code!=200:
    print(f'登录失败!错误代码:{str(res.status_code)}')
else:
    print(res.text)

在尝试登陆时老是失败。后来在其他网站上找到下面的解决思路:

在requests中,如果直接使用get()或post()等方法是可以做到模拟网页的接口请求,但是每次发起请求结束后它就结束了,并不会保存相关的验证信息,如cookies/token; 比如第一次使用post()请求登录了某个网站,第二次想获取成功登录后的用户个人信息,再一次发起post()请求时它会要求你需求先登录,明明第一次请求时已经登录了,为什么第二次还提示要先登录呢? 实际上两次请求相当于使用了两个浏览器去访问,是两个完全不相关的会话,因此第二次请求是拿不到用户信息的。 requests中的session()对象能够让我们跨http请求保持某些参数,即让同一个session对象发送的请求头携带某个指定的参数。当然,最常见的应用是它可以让cookie保持在后续的一串请求中。

这段话简而言之就是:每次使用requests.get或post都相当于使用不同浏览器打开一个链接,若要保持同一个浏览器打开不同链接就必须使用session。

因此我把上面的代码中的request改为:

import requests
from urllib.parse import urlencode

headers={'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36'}

# 使用session
se=requests.session()

res=se.get('https://。。。。。。.com',headers=headers)
if res.status_code==200:
    res=res.text
else:
    print('打开网页失败。')
    exit()

# 查找网页源代码中的hash值
try:
    hash_value=re.search('name="hash" value="(.*?)"',res)[1]
except Exception:
    print('找不到hash值')
    exit()

# 登录用的表单数据
data={'username':'这里填你的用户名',
      'password':'你的密码',
      'hash': hash_value,
      }

# 用urlencode把登录表单数据编译成url
posturl='https://。。。。。。.com/login?'+urlencode(data)

res=se.post(posturl,headers=headers,timeout=10)

if res.status_code!=200:
    print(f'登录失败!错误代码:{str(res.status_code)}')
else:
    print(res.text)

又是失败!可是明明是按照教程来写的,难道网站又设了什么JS代码拦截?

再参考其他教程,改代码调试,意想不到的是,原来错就错在session的写法:

错误写法:se = requests.session()

正确写法:se = requests.Session()

Session()开头的S一定要大写!这是很多人入门时犯的低级错误。小写的话虽然代码可以通过,但没有起到实质性作用导致登录失败,因此千万记住这个一定要写成Session()。

扫描二维码关注公众号,回复: 14815885 查看本文章

猜你喜欢

转载自blog.csdn.net/Scott0902/article/details/128899017