requests请求状态保持-登录github为例

模拟登录-状态保持

​ ---- 以登录 github 为例

1 .页面分析:

  • 登录页 ( https://github.com/login ) 网页源代码能找到 form 表单的提交方式是 post 请求,登录账号并且打开 Chrome 浏览器的调试工具 ( F12 - Network - all ) 查看提交请求,能到以下信息

    • 提交数据为:

      commit: Sign in
      utf8: ✓
      authenticity_token: UCGHpjglqtJ70hl/3ygpPUPVGLukUm0ACcYJ47BGb4pyyz6s+V5GHQSYQp419+EYcyUfJx3j/cGJziQonKIeAw==
      login: email
      password: passwd
      

    其中 login 和 password 的参数值为用户的邮箱和密码,每个人不一样。

    分析 authenticity_token 这个参数值是没有规律的,但是细心点会发现,在登录页的网页源代码中的 form 标签中有一个 type 为 "hidden" 并且 name 参数 为 "authenticity_token" 的 <input> 子标签,其 value 参数值就是提交数据中的值。

2.流程说明

  • 使用 requests.Session() 方法创建一个 Session 对象,这样可以做到模拟同一个会话而不用担心 Cookies 的问题。
  • get 请求登录页,xpath 解析出 "authenticity_token" 的值。为避免反爬,请加上请求头 headers。
  • 构建 post 请求,提交数据数据为上述的那些,请自行验证其正确性。为避免反爬,请加上请求头 headers。
  • 登录成功后会自动重定向到首页,此时已经做到了session 的状态保持。
  • 请求个人主页解析自己的 用户名 和 邮箱。(这一步只是测试。)

3.代码示例

  • demo版(面向流程)只是为了跑通流程,之后会改为面向对象版本。

    import requests
    from lxml import etree
    
    # 登录页get请求URL
    base_url = 'https://github.com/login'
    
    # 登录post提交URL
    login_url = 'https://github.com/session'
    
    # github个人主页
    profile_url = 'https://github.com/settings/profile'
    
    # 登录页headers
    headers = {
      'Referer':'https://github.com/',
      'Host':'github.com',
      'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36',
    }
    
    # post 提交数据
    post_data = {
      'commit':'Sign in',
      'utf8':'✓',
      'login':'email@mail.com',
      'password':'password',
    }
    
    # 保持会话式请求
    s = requests.Session()
    # 请求登录页获取 token
    res_login = s.get(url=base_url, headers=headers)
    
    if res_login.status_code == requests.codes.ok:
      index_html = res_login.text
      index_html_obj = etree.HTML(index_html)
      # 获取 authenticity_token,在post提交时会作为一个键值对传入
      token = index_html_obj.xpath('//div[@id="login"]/form/input[@name="authenticity_token"]/@value')[0]
      post_data['authenticity_token'] = token
      # 登录提交
      res_index = s.post(url=login_url, headers=headers, data=post_data)
      if res_index.status_code == requests.codes.ok:
          print("登录成功,开始请求个人主页")
    
          # 进入个人中心
          res_profile = s.get(url=profile_url, headers=headers)
          if res_profile.status_code == requests.codes.ok:
              print("请求个人主页成功,开始解析数据")
              profile_html = res_profile.text
              profile_obj = etree.HTML(profile_html)
              username = profile_obj.xpath('//div[@class="column two-thirds"]/dl[contains(@class,"form-group")]/dd/input[@id="user_profile_name"]/@value')[0]
              print("用户名:", username)
              email = profile_obj.xpath('//div[@class="column two-thirds"]/dl[2]/dd/select/option[2]/text()')[0]
              print("邮箱:", email)
          else:
              print("请求个人主页失败")
      else:
          print("登录失败")
    
    
  • 面向对象版本

    import requests
    from lxml import etree
    
    class GithubLogin(object):
      def __init__(self):
          # 登录页get请求URL
          self.base_url = 'https://github.com/login'
          # 登录post提交URL
          self.login_url = 'https://github.com/session'
          # github个人主页
          self.profile_url = 'https://github.com/settings/profile'
          # 登录页headers
          self.headers = {
              'Referer': 'https://github.com/',
              'Host': 'github.com',
              'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36',
          }
          self.session = requests.Session()
      
        # 获取登录页的 authenticity_token 值
      def token(self):
          res = self.session.get(url=self.base_url, headers=self.headers)
          if res.status_code == requests.codes.ok:
              res_obj = etree.HTML(res.text)
              token_value = res_obj.xpath('//div[@id="login"]/form/input[@name="authenticity_token"]/@value')[0]
              return token_value
      
      def login(self, email, passwd):
          post_data = {
              'commit': 'Sign in',
              'utf8': '✓',
              'login': email,
              'password': '753159wt',
              'authenticity_token': self.token()
          }
            
            # 登录 post 提交表单
          res_index = self.session.post(url=self.login_url, headers=self.headers, data=post_data)
          if res_index.status_code == requests.codes.ok:
              self.repository(res_index.text)
          
            # 请求个人中心页面
          res_profile = self.session.get(url=self.profile_url, headers=self.headers)
          if res_profile.status_code == requests.codes.ok:
              self.getProfile(res_profile.text)
      
      def repository(self, text):
          res_obj = etree.HTML(text)
          repo_list = res_obj.xpath('//div[@class="Box-body"]/ul/li//a/@href')
          for repo in repo_list:
              print(repo)
              
      def getProfile(self, text):
          res_obj = etree.HTML(text)
          username = res_obj.xpath('//div[@class="column two-thirds"]/dl[contains(@class,"form-group")]/dd/input[@id="user_profile_name"]/@value')[0]
          print("用户名:", username)
          email = res_obj.xpath('//div[@class="column two-thirds"]/dl[2]/dd/select/option[2]/text()')[0]
          print("邮箱:", email)
          
          
    if __name__ == '__main__':
      alice_login = GithubLogin()
      alice_login.login('email@mail.com', 'password')
    
    
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值