美文网首页
requests请求状态保持-登录github为例

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

作者: 北游_ | 来源:发表于2018-06-20 22:55 被阅读222次

    模拟登录-状态保持

    ​ ---- 以登录 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')
      
      

    相关文章

      网友评论

          本文标题:requests请求状态保持-登录github为例

          本文链接:https://www.haomeiwen.com/subject/eyjfyftx.html