python_模拟登录知乎,python模拟,如何登录知乎?  首


如何登录知乎?

  首先要分析,进行知乎验证的时候,知乎服务器需要我们提交什么数据,提交的地址。先进行几次登录尝试,通过浏览器中network中查看数据流得知,模拟登录知乎需要提供5个数据,分别是_xsrf、password、captcha_type、captcha、phone_num,这个是手机号码进行验证登录,提交地址https://www.zhihu.com/login/phone_num ,那,开始获取这些个数据,其中那个图片验证码是最难得,通过第三方插件zheye进行验证码解析,就可以解决问题

如何做?

  1. 请求知乎登录页面,并解析获得_xsrf值

  2. 请求验证码url获得验证码图片,交个zheye解析出结果并拼接出知乎想要的captcha值

  3. 从知乎验证提交表单中获取captcha_type的值,并获取表单提交地址

  4.captcha_type、password 对应用户名和密码

  5. 提交数据,获取返回的response,通过判断response数据获取是否登录成功

#!/usr/bin/python3import requestsimport reimport jsonfrom time import sleepfrom random import choice, randintfrom zhihu_yanzheng.zheye import zheyeheaders = {    ‘pragma‘: ‘no-cache‘,    ‘Referer‘: ‘https://www.zhihu.com/signin‘,    ‘user-agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36‘}# 生成全局的session值session = requests.session()def random_sleep():    # 随机暂停,模拟人访问    while choice([0, 1]):        sleep(choice([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]))def get_xsrf():    """    获取知乎页面_xsrf的值    :param url:    :return:    """    zhihu_url = ‘https://www.zhihu.com/signin‘    # 建立映射,增加程序的可阅读性    xsrf_value = 1    while True:                random_sleep()                resp = session.get(zhihu_url, headers=headers)        # 检查是否返回正确        resp.raise_for_status()        # 设置网页编码        resp.encoding = resp.apparent_encoding        # 获取_xsrfde值        _xsrf = re.match(r‘.*name="_xsrf" value="(.*?)"‘, re.sub(r‘[\r\t\n]‘, ‘‘, resp.text)).group(xsrf_value)        # 保证有_xsrf数据        if _xsrf:            break    return _xsrfdef get_img_data():    """    获取图片并且获得图片的验证码数据    :return:    """    while True:        random_int = str(randint(1, pow(10, 13)))        # 获取图片的值        img_url = ‘https://www.zhihu.com/captcha.gif?r=%s&type=login&lang=cn‘ % random_int                random_sleep()        # 获取图片        img_resp = session.get(img_url, headers=headers)        with open(‘zhihu_img.jpg‘, ‘wb‘) as f:            f.write(img_resp.content)        # 解析图片        z = zheye()        img_yanzhe = z.Recognize(‘zhihu_img.jpg‘)        # 把获得的坐标按x进行排序 [(48.647850377664284, 315.97586850515023), (49.944977855563351, 146.27730894630022)]        img_yanzhe.sort(key=lambda x: x[1])        # 知乎提交的位置数据和zheye解析的数据位置相反,置换成知乎要求的数据        img_data = []        for y, x in img_yanzhe:            # zheye中图片为400*88像数,知乎要求为200*44,所有每个值都要除以2            img_data.append((x / 2, y / 2))        # 有数据表示解析成功,没数据重新请求数据再次解析        if img_data:            break    return img_datadef get_captcha_data(img_data):    """通过字符串格式化得到知乎想要的captcha值"""    # captcha:{"img_size":[200,44],"input_points":[[120.375,34],[160.375,36]]}    # first, second, third分别对应第一、第二、第三值,x,y 对应其中x,y坐标值    first, second, third, x, y = 0, 1, 2, 0, 1    if len(img_data) == 1:        captcha = ‘{"img_size":[200,44],"input_points":[[%.2f,%.2f]]}‘                   % (img_data[first][x], img_data[first][y])    elif len(img_data) == 2:        captcha = ‘{"img_size":[200,44],"input_points":[[%.2f,%.2f],[%.2f,%.2f]]}‘                   % (img_data[first][x], img_data[first][y], img_data[second][x], img_data[second][y])    elif len(img_data) == 2:        captcha = ‘{"img_size":[200,44],"input_points":[[%.2f,%.2f],[%.2f,%.2f],[%.2f,%.2f]]}‘                   % (img_data[first][x], img_data[first][y], img_data[second][x], img_data[second][y], img_data[third][x], img_data[third][y])    return captchadef get_form_data():    """获取知乎想要的表单数据"""    _xsrf = get_xsrf()    img_data = get_img_data()    captcha = get_captcha_data(img_data)    form_data = {        ‘_xsrf‘: _xsrf,        ‘password‘: ‘password‘,        ‘captcha_type‘: ‘cn‘,        ‘captcha‘: captcha,        ‘phone_num‘: ‘phone_num‘,    }    return form_datadef go_login(post_url):    """提交表单并获取返回值"""    from_data = get_form_data()        random_sleep()    # 提交验证信息,不允许重定向    resp_yan = session.post(post_url, headers=headers, data=from_data, allow_redirects=False)    # 获取返回的值    result = resp_yan.text    return json.loads(result)if __name__ == ‘__main__‘:    post_url = ‘https://www.zhihu.com/login/phone_num‘    result = go_login(post_url)    print(result)

  

python_模拟登录知乎

评论关闭