requests模块高级应用---模拟登录

  • 模拟登录目的:

    爬取某些用户的用户信息。

  • 需求说明:

    对古诗词网进行模拟登录。

  • 编码流程:
  1. 爬取首页数据,获取验证码信息并保存
  2. 通过超级鹰对验证码进行自动识别
  3. 点击登录后获取到登录页面的URL,模拟对登录页面发起post请求,参数中携带验证码(动态变化的)
  4. 直接献上代码:
    # @Time : 2022/1/20 0020 9:56
    # @Author : Tzy0425
    # @File : 古诗词网实现模拟登陆.py
    
    import requests
    from lxml import etree
    from chaojiying import Chaojiying_Client
    
    # 封装识别验证码图片的函数
    def getCode(filePath):
        chaojiying = Chaojiying_Client('超级鹰用户账号', '超级鹰用户密码', '软件ID')  
        im = open('code_gushi.jpg', 'rb').read()  # 本地图片文件路径
        return chaojiying.PostPic(im, 1004)
    
    
    # 对验证码图片进行捕获和识别
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36'
    }
    
    url = 'https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx'
    page_text = requests.get(url=url,headers=headers).text
    tree = etree.HTML(page_text)
    code_src = 'https://so.gushiwen.cn' + tree.xpath('//*[@id="imgCode"]/@src')[0]
    code_data = requests.get(url=code_src,headers=headers).content
    with open('./code_gushi.jpg','wb') as fp:
        fp.write(code_data)
    
    # 解析动态参数
    __VIEWSTATE = tree.xpath('//*[@id="__VIEWSTATE"]/@value')[0]
    __VIEWSTATEGENERATOR = tree.xpath('//*[@id="__VIEWSTATEGENERATOR"]/@value')[0]
    
    code_text = getCode('code_gushi.jpg')
    code = code_text.get('pic_str')
    print(code)
    
    login_url = 'https://so.gushiwen.cn/user/login.aspx?from=http%3a%2f%2fso.gushiwen.cn%2fuser%2fcollect.aspx'
    data = {
        '__VIEWSTATE':__VIEWSTATE,
        '__VIEWSTATEGENERATOR':__VIEWSTATEGENERATOR,
        'from':' http://so.gushiwen.cn/user/collect.aspx',
        'email':' 自己的账号',
        'pwd':' 自己的密码',
        'code':code,
        'denglu':' 登录',
    }
    # 使用session进行post请求的发送
    response = requests.post(url=login_url,data=data,headers=headers)
    login_page_text = response.text
    print(response.status_code)
    with open('./gushici.html','w',encoding='utf-8') as fp:
        fp.write(login_page_text)

    正常情况下,上述代码便可成功的模拟用户进行登录,运行后生成的HTML应为登录成功后跳转的首页,但运行后却发现,返回的状态码虽然是200,但生成的页面却是登录页面而不是登录成功后的用户界面,Why???

 

 

   别急,从以下几点解释后就会明白。

  • http / https协议特性:

    无状态,也就是当用户向服务器发出请求后,服务端并不会记录当前用户的相关状态。

  • 没有请求到对应页面数据的原因:

    所以说,代码中发起的第二次基于个人主页页面(即登录成功后跳转到的页面)请求的时候,前提是已经登录成功,但由于http / https协议无状态的特性,服务端并不知道该请求是基于登录状态下的请求,所以它会重新返回给你登录界面,那么服务端是通过什么记录客户端的相关状态的呢? ------ cookie

  • cookie:用来让服务端记录客户端的状态
  1. 手动处理:通过抓包工具获取cookie值,将该值封装到headers中。(不建议,因为有的cookie是动态变化的,而且操作繁琐)
  2. 自动处理:首先我们要知道,cookie值是来源于在登录时发送的post请求后,由服务端创建。其次,要用到session会话对象,它可以进行请求的发送(编码方式和requests相同),并且如果在请求的过程中产生了cookie,则该cookie会被自动保存在session对象中。
  3. session使用流程:

    (1)创建一个session对象:session = requests.Session()

    (2)使用session对象进行模拟登录post请求的发送

    (3)session对象对个人主页对应的get请求进行发送

  那么,经过分析,其实只需要把之前通过requests进行请求,改为通过session进行请求即可,对于代码来说就是在最开始创建session对象,然后把后面的requests的部分改为session即可。

 

  最后,在介绍一种反爬机制与对应的反反爬策略:

 

  • 代理:存在一种反爬机制,是通过限制单位时间内ip的访问次数,反反爬策略就用到了ip代理。
  1. 代理相关的网站:快代理、西祠代理、www.goubanjia.com
  2. 代理ip的类型:http与https,分别应用于对应的协议当中
  3. 代理ip的匿名度:

    (1)透明:服务器知道该次请求使用了代理,也知道请求对应的真实ip

    (2)匿名:服务器知道使用了代理,但不知道真实ip

    (3)高匿:服务器不知道使用了代理,更不知道真实的ip

  相关代码:

    只需要在requests的请求参数中添加proxies,然后赋一个代理ip即可。

import requests
url = 'https://www.baidu.com/s?wd=ip'
headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'
}

page_text = requests.get(url=url,headers=headers,proxies={"https":'222.110.147.50:3128'}).text

with open('ip.html','w',encoding='utf-8') as fp:
    fp.write(page_text)

 

posted @ 2022-01-20 11:43  Sunshine_y  阅读(420)  评论(0编辑  收藏  举报