github地址:ZhihuLogin
最近工(xian)作(de)不(dan)忙(teng), 一直写Android没意思, 于是就学习下python, 以下记录我实现模拟知乎登录的探索过程。
在开始之前, 我的个人习惯是先做好功课, 以下几篇文章是我提前找的参考资料:
Python 爬虫之模拟知乎登录
零基础自学用Python 3开发网络爬虫(四): 登录
下面我就正式开始了。
首先我退出知乎账号, 到知乎的登录页。
填上账号密码, 准备登录, 但是当这个倒立的文字的验证码出来的时候, 我忽然意识到something went wrong。因为在我准备的“参考资料”中, 验证码还不是这种点击倒立的文字,而是那种普通的需要填写字母或者数字的验证码, 也就是说知乎的前端又改版了, 信息过时了, 之前的登陆方法也许就不能用了。不过我们还是继续看看吧。
在我随便点了几个文字, 然后点击登录。因为我是随便点的, 当然结果是验证失败。
image.png然后我观察到提交的表单数据是这样的
image.pngemail是登录的邮箱账号, password是密码(我不会让你看到的), 都是明文。
_xsrf是什么?在我事先准备的“参考资料”里说是一串伪随机数, 是用来防止跨站请求伪造的。 什么意思呢?我也看不懂。 但是要得到这个值其实并不难,它其实隐藏在页面的某个标签中
然后用正则表达式或者beautifulSoup把这个值提取出来就行了,参考代码:
def get_xsrf():
url = 'https://www.zhihu.com'
response = session.get(url, headers=headers)
soup = BeautifulSoup(response.text, 'lxml')
# <input type="hidden" name="_xsrf" value="0448114b8b68c194d9fc9d831d251379">
tag = soup.find('input', attrs={'name': '_xsrf'})
return tag['value']
captcha_type是应该是一个常量值cn, 也不知道是不是必需的
captcha是一个字典, 应该就是点击那张倒立的文字的图片所生成的
字典中的"input_points":[[87.875,32]]应该是点击的位置信息
然而这些信息我应该怎么得到呢?
我最终的答案是:得不到。
是的, 以我目前的作为一个python初学者并且对前端js什么的也一窍不通的水平来说, 我得不到。但是就这样完了吗?当然不(废话不然我还写这篇文章干嘛)。
虽然在电脑网页端得不到这个input_points信息, 但是如果换成手机端的网页, 就不会出现那种倒立的文字的验证码了, 以前的模拟登陆方式就又能用了
image.png
这种绕开倒立的文字的验证码的方式我是怎么想到的呢?其实我只是看了别人的代码而已(不然我能怎么办?)
image.png
参考自知乎上某位大佬的github上的代码(https://github.com/xchaoinfo/fuck-login/blob/master/001%20zhihu/zhihu.py)
然后我也参考着写了一份(其实跟大佬的代码没什么差别)
首先需要安装然后导入这些包
import requests, time, os
from bs4 import BeautifulSoup
from http import cookiejar
接着定义一个全局的session, 用来保存和复用cookies。登录之后获取的cookies保存在本地的cookies.txt文件中, 下次需要登录时再从中获取cookies。为什么要复用cookies?因为这样一次登陆之后你在浏览别的网页你就不需要再次验证身份了。关于session和cookies如果不是太清楚具体的可以看慕课网的这个教程, 我觉得讲的挺好。
Requests库-Session和Cookies
注意这里的user-agent也就是用户代理要写成手机端的, 比如这里是Android手机。
session = requests.session()
session.cookies = cookiejar.LWPCookieJar(filename='cookies.txt')
headers = {
'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36'
}
先判断是否已经登陆, 也就是说先看看是否已经能够查看自己的个人主页的信息,如果可以,说明已经登陆了,那么接下来爬虫就可以开始爬取信息了,如果不行,说明还需要重新登陆
def isLogin():
# 通过查看用户个人信息来判断是否已经登录
url = "https://www.zhihu.com/settings/profile"
response = session.get(url, headers=headers, allow_redirects=False)
code = response.status_code
if code == 200:
return True
else:
return False
手机端网页登陆时需要提交的表单参数有4个
data = {
'_xsrf': _xsrf,
'password': password,
'email': email,
'captcha': captcha
}
password和email是密码和登陆的邮箱账号,_xsrf上面也说过了。captcha是4位由字母和数字组成的验证码, 需要先将验证码图片下载到本地, 然后人眼识别(是的你没看错)
def get_captcha():
t = str(int(time.time() * 1000))
captcha_url = 'https://www.zhihu.com/captcha.gif?r=' + t + "&type=login"
response = session.get(captcha_url, headers=headers)
with open('captcha.gif', 'wb') as f:
f.write(response.content)
os.startfile('captcha.gif')
return input('请输入验证码: ')
上面那段代码会在验证码图片下载完成之后自动打开验证码图片, 然后你观察一下, 填上验证码。至于验证码图片的链接地址的拼接方式是怎么得到的, 反正我是抄的。
然后就可以登陆了,记得登陆之后要把cookies保存下来, 这点非常重要, 因为这样你打开知乎的别的网页就不需要重新登陆了。
def login(email, password, _xsrf, captcha):
data = {
'_xsrf': _xsrf,
'password': password,
'email': email,
'captcha': captcha
}
login_url = 'https://www.zhihu.com/login/email'
response = session.post(login_url, data=data, headers=headers)
print('response.json() =', response.json())
# 保存cookies到本地
session.cookies.save()
效果演示和github地址(重要的事情再说一遍):ZhihuLogin
最后再说一点, 手机端登录是怎么知道那几个需要提交的参数的呢?应该是抓包, 但是知乎是https, https要怎么抓包?我找了一点资料https://www.zhihu.com/question/41751887
不过具体的我还没有试过, 有问题欢迎一起讨论
网友评论