如何登陆知乎?python
首先要分析,进行知乎验证的时候,知乎服务器须要咱们提交什么数据,提交的地址。先进行几回登陆尝试,经过浏览器中network中查看数据流得知,模拟登陆知乎须要提供5个数据,分别是_xsrf、password、captcha_type、captcha、phone_num,这个是手机号码进行验证登陆,提交地址 https://www.zhihu.com/login/phone_num ,那,开始获取这些个数据,其中那个图片验证码是最可贵,经过第三方插件zheye进行验证码解析,就能够解决问题json
如何作?浏览器
1. 请求知乎登陆页面,并解析得到_xsrf值服务器
2. 请求验证码url得到验证码图片,交个zheye解析出结果并拼接出知乎想要的captcha值session
3. 从知乎验证提交表单中获取captcha_type的值,并获取表单提交地址app
4. captcha_type、password 对应用户名和密码dom
5. 提交数据,获取返回的response,经过判断response数据获取是否登陆成功post
#!/usr/bin/python3 __author__ = 'beimenchuixue' __blog__ = 'http://www.cnblogs.com/2bjiujiu/' import requests import re import json from time import sleep from random import choice, randint from zhihu_yanzheng.zheye import zheye headers = { '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 _xsrf def 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_data def get_captcha_data(img_data): """经过字符串格式化获得知乎想要的captcha值""" # captcha:{"img_size":[200,44],"input_points":[[120.375,34],[160.375,36]]} # first, second, third分别对应第1、第2、第三值,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 captcha def 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_data def 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)