新版知乎登录request登录(2)(类编程)

原创 2018年04月17日 21:54:15

接上一篇,用类重构了代码,方法是一致的,但是看起来更整洁些。
不多说了,上代码:

#! /usr/local/bin python3.6
"""
@Time    : 2018/4/17 20:00
@Author  : ysj
@Site    : 
@File    : ZhiHuLogIn.py
@Software: PyCharm
"""
import time
import requests
import base64
import json
from hashlib import sha1
import hmac
import os
import uuid
# from PIL import Image
# from multiprocessing import Process
import http.cookiejar as cookielib

# 忽略 InsecureRequestWarning报错; verify=True 即可
# requests.packages.urllib3.disable_warnings()


class ZhiHu:
    """
    知乎登录类,实例化后,self.session即相当于登录客户端requests.session
    """
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0',
               'HOST': 'www.zhihu.com', 'Referer': 'https://www.zhihu.com/signin?next=%2F',
               'Authorization': 'oauth c3cef7c66a1843f8b3a9e6a1e3160e20'}

    login_url = 'https://www.zhihu.com/api/v3/oauth/sign_in'
    captcha_url = 'https://www.zhihu.com/api/v3/oauth/captcha?lang=en'
    check_url = 'https://www.zhihu.com/inbox'
    post_data = {
        'client_id': 'c3cef7c66a1843f8b3a9e6a1e3160e20',
        'grant_type': 'password',
        'timestamp': str(int(time.time())),
        'source': 'com.zhihu.web',
        'signature': None,
        'username': None,
        'password': None,
        'captcha': None,
        'lang': 'en',
        'ref_source': 'homepage',
        'utm_source': ''
    }
    """
    测试数据,固定签名,无需签名
    post_data = {
        'client_id': 'c3cef7c66a1843f8b3a9e6a1e3160e20',
        'grant_type': 'password',
        'timestamp': '1515398025518',
        'source': 'com.zhihu.web',
        'signature': '30b129980d00e5efb09f16b0334bf4e8601b060b',
        'username': 1,
        'password': 2,
        'captcha': 3,
        'lang': 'en',
        'ref_source': 'homepage',
        'utm_source': ''
    }
    """

    def __init__(self, account, password, cookie_file='zhihu_cookie.txt'):
        self.session = requests.session()
        self.session.headers = self.headers
        self.cookie_file = cookie_file
        self.session.cookies = cookielib.LWPCookieJar(filename=self.cookie_file)
        self.username = account
        self.password = password
        self.check_count = 0
        try:
            self.session.cookies.load(ignore_discard=True, ignore_expires=True)
            print('cookie信息加载成功')
        except FileNotFoundError:
            print("cookie信息加载失败")
            self.login()
        else:
            if not self.check_login():
                print('cookie登录失败,即将重新登录')
                self.login()
        # self.check_login()

    def login(self):
        """整个登录过程"""
        self.check_count = 0
        self.post_data['username'] = self.username
        self.post_data['password'] = self.password
        self.post_data['captcha'] = self.check_captcha()
        self.post_data['signature'] = self.get_signature()
        self.sign_in()

    def check_login(self):
        """传入session对象, 使用地址判断是否登录"""
        # 不允许跳转,不然总是为200
        res = self.session.get(self.check_url, verify=True, allow_redirects=False)
        code = res.status_code
        if code < 300:
            print('已登录成功')
            return True
        else:
            print('未登录或登录失败')
            return False

    def sign_in(self):
        """实际登录api"""
        response = self.session.post(self.login_url, data=self.post_data, verify=True)
        if self.check_login():
            self.session.cookies.save(ignore_expires=True, ignore_discard=True)
            return True
        else:
            print(response.json())

    def check_captcha(self):
        response = self.session.get(self.captcha_url, verify=True)
        show_captcha = response.json()['show_captcha']
        if not show_captcha:
            return None
        else:
            # 有验证吗,重新请求获取验证码
            response = self.session.put(self.captcha_url, verify=True)
            img = json.loads(response.content)['img_base64']
            img = img.encode('utf-8')
            img_data = base64.b64decode(img)
            filename = str(uuid.uuid4()) + 'tpm.gif'
            with open(filename, 'wb') as f:
                f.write(img_data)
            # 多进程显示图片异常,暂时舍弃该功能
            # im = Image.open(filename)
            # sub = Process(target=im.show)
            # sub.start()
            # im.show()
            captcha = input('请输入当前目录下图片%s,的验证码:' % filename)
            # sub.terminate()
            # im.close()
            os.remove(filename)
            data = {'input_text': captcha}
            response = self.session.post(self.captcha_url, data=data, verify=True)
            try:
                result = response.json()
            except Exception as ex2:
                print('验证码的post请求响应失败,原因:{}'.format(ex2))
                """ 验证码失败,则再递归3次重新获取验证码"""
                self.check_count += 1
                if self.check_count < 4:
                    self.check_captcha()
            else:
                if result.get('success'):
                    return captcha
                else:
                    print(result)
                    """ 验证码失败,则再递归3次重新获取验证码"""
                    self.check_count += 1
                    if self.check_count < 4:
                        self.check_captcha()

    def get_signature(self):
        """知乎登录签名,先加载默认字符串
        实测比较死板,固定拿任意个对应的时间戳和signature 直接加载到请求参数即可跳过签名步骤
        """
        def ensure_bytes(value):
            """字节确保,方便后续加密签名"""
            return value if isinstance(value, bytes) else value.encode('utf-8')

        hm = hmac.new(b'd1b964811afb40118a12068ff74a12f4', None, sha1)
        try:
            kwargs = self.post_data
            hm.update(ensure_bytes(kwargs['grant_type']))
            hm.update(ensure_bytes(kwargs['client_id']))
            hm.update(ensure_bytes(kwargs['source']))
            hm.update(ensure_bytes(kwargs['timestamp']))
        except KeyError as ex:
            print('缺少参数', ex)
        else:
            return hm.hexdigest()


if __name__ == '__main__':
    login = ZhiHu('18516157608', '*****')
    print(login.session.get(login.check_url, allow_redirects=False).status_code)
    # 未登录的为302
    print(requests.get('https://www.zhihu.com/inbox', headers=ZhiHu.headers, allow_redirects=False).status_code)

Scrapy练习爬知乎第一辑

模仿网上的Scrapy程序,自己写了个爬虫。虽然是模仿,但是呢,好多都是自己去实践错了对了,整天都在苦闷之中度过,没办法,我的IQ较低,总是要学很久才能懂。。。。。。。 ps:运行这个程序你要安装sc...
  • clownstar
  • clownstar
  • 2015-06-14 14:22:21
  • 2243

转载知乎-前端汇总资源

学习编程专栏连载的练手项目篇,如有兴趣可以访问前三篇: 有哪些适合新手练手的Java项目? - 学习编程 - 知乎专栏 有哪些适合新手练手的Java Web项目? - 学习编程 - 知乎专栏 ...
  • ssisse
  • ssisse
  • 2016-08-30 18:21:35
  • 952

android 知识点收集

作者:Rocko 链接:https://www.zhihu.com/question/33636939/answer/57297329 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,...
  • u011118784
  • u011118784
  • 2017-08-08 09:56:09
  • 195

使用Python模拟登录知乎

小试牛刀:使用Python模拟登录知乎 Posted on 2016-11-05   |   In Spider   |     |   views : 1610 最近突然对爬虫...
  • da_guo_li
  • da_guo_li
  • 2017-06-07 16:30:27
  • 504

新版知乎登录request登录(1)(函数式编程)

新版知乎登录request登录 运行脚本前提 pip3 install requests 更换用户名,密码,直接运行即可,运行时可能需要输入验证码,验证位于当前目录下。 具体代码,及关键步...
  • qq_33162635
  • qq_33162635
  • 2018-04-16 22:21:45
  • 15

如何防止 Android 应用被二次打包?(转自知乎)

作者:轩辕 链接:https://www.zhihu.com/question/41368839/answer/112182560 来源:知乎 著作权归作者所有,转载请联系作者获得授权。 谢邀 题主...
  • egostudio
  • egostudio
  • 2016-11-28 16:35:24
  • 1325

使用Fidder修改https请求,替换本地js文件

在学习爬虫的时候,一个案例是爬取知乎上的问题。由于视频录制时间与看的时候相差较远,知乎的登录已经改版并且难度加大后来网上找到一个文章模拟登陆知乎(最新版)为了尝试获取signature的加密方式,使用...
  • sq574146616
  • sq574146616
  • 2018-02-14 01:08:37
  • 72

新版知乎模拟登录

  • 2018年04月08日 17:21
  • 3KB
  • 下载

登录知乎

import requests with open('d://cookie.txt','r') as f: cookies={} for line in f.read().split('...
  • qq_17172105
  • qq_17172105
  • 2016-12-29 20:18:29
  • 260

数据分析之——微信好友分析

itchat中午吃午饭的时候,无意间浏览到某公众号的一篇文章,是关于爬微信好友的。自从爬虫工程师转数据分析师以来,很久没玩过爬虫了,于是乎玩心一起,吃完饭之后自己便尝试起来。itchat 包,已经完成...
  • Lee20093905
  • Lee20093905
  • 2018-01-13 17:53:52
  • 727
收藏助手
不良信息举报
您举报文章:新版知乎登录request登录(2)(类编程)
举报原因:
原因补充:

(最多只允许输入30个字)