Scrapy实现最新的知乎模拟登陆

作者:Wilson_Iceman 出处:http://blog.youkuaiyun.com/Wilson_Iceman 欢迎转载, 但请保留这段声明。多谢!

最近一直在尝试使用Scrapy实现知乎的模拟登陆,终于实现了,今天在这里总结一下。

很多朋友可能知道了知乎进行了改版,特别是登录这一部分,不再使用传统的Form表单的形式,而是使用了Multipart/form-data的这种结构来提交表单数据,这就给我们模拟登陆知乎增加了不少麻烦。最近一直在尝试各种办法,后来又结合网络中其他朋友的意见,终于实现了使用Scrapy来模拟登陆知乎。

首先和之前的登录不同的是,之前登录有两个接收表单的地址,一个是https://www.zhihu.com/login/phone_num,一个是https://www.zhihu.com/login/email。现在知乎登录统一都改成了https://www.zhihu.com/api/v3/oauth/sign_in。所以我们发送表单数据的时候实际上是要发送给这个地址。另一个不同的地方是,之前在headers中需要一个_xsrf参数,这个参数是动态生成了。但是现在除了这个参数外,还需要另一个参数X-UDID。

接下来我们看看最近的知乎模拟登陆需要提交的表单数据有哪些。

从上面的截图中我们可以看到,之前的知乎模拟登陆只需要三个参数,分别是_xsrf, username, password,可是现在我们需要

这么多的字段才能完成模拟登陆的事情。现在需要做的是看看哪些字段是固定的,哪些字段是动态生成的。

我用了几个假的账号来尝试找出哪些字段是固定的,哪些字段是动态生成的。

  • client_id : c3cef7c66a1843f8b3a9e6a1e3160e20 (目前是固定的)
  • grant_type : password (固定)
  • timestamp : (动态生成)
  • source: com.zhihu.web (固定)
  • signature : (动态生成)
  • username : (用户输入)
  • password : (用户输入)
  • captcha : (动态生成,但是账号密码正确时并不需要)
  • lang : 'en' (固定)
  • ref_source : 'homepage' (固定)
  • utm_source : "" (固定)
通过上面的总结可以看到,我们的主要任务是如何模拟出上面动态生成的几个字段。其中要注意captcha(验证码)这个字段,它
虽然并不需要我们来处理,但是必须要发送一个验证码的请求,否则服务器会返回错误。最后就剩下timestamp和signature这两个字
段了,时间戳好办,最麻烦的就是这个signature字段。
这里我们自己定义了三个函数,get_headers,get_data,check_captcha,分别用来得到headers请求头部数据,form-data表
单数据以及发送一个验证码的请求。
get_headers代码如下:
def get_headers(self):
		'从网页源代码内解析出 uuid与Xsrftoken'
		z1 = self.s.get('https://www.zhihu.com/')
		sel = Selector(z1.text)
		jsdata = sel.css('div#data::attr(data-state)').extract_first()
		xudid = json.loads(jsdata)['token']['xUDID']
		xsrf = json.loads(jsdata)['token']['xsrf']
		headers = headers_raw_to_dict(post_headers_raw)
		headers['X-UDID'] = xudid
		headers['X-Xsrftoken'] = xsrf
		return headers

这部分代码比较简单,主要就是通过css选择器来找到登录页面中隐藏的headers中的两个字段的参数,分别是X-UDID和
X-Xsrftoken,其中还有一段是固定的,直接定义一个固定值就好。
get_data函数的代码 比较多,大家可以在最后全部代码中看到zehbufen
新版的知乎登录中要动态的生成signature,而这个signature又是用js来生成的。本人的Python
水平有限,无法用Python来完全模拟出这段代码,只好原封不动的拿过来,然后使用Pyexecjs这个库来执行JavaScript语言。有兴趣
的同学可以帮我来实现这段代码的Python化。
好了,现在headers得到了,data也得到了,剩下的就是验证码了。
	def check_captcha(self, headers, cn=True):
		'发送一个验证码的请求,不管需不需要都必须发送这个请求'
		if cn:
			url = 'https://www.zhihu.com/api/v3/oauth/captcha?lang=cn'
		else:
			url = 'https://www.zhihu.com/api/v3/oauth/captcha?lang=en'
		headers.pop('X-Xsrftoken')
		z = self.s.get(url, headers=headers)
		show_captcha = json.loads(z.text)['show_captcha']
		if show_captcha:
			with open('captcha.jpg', 'wb') as f:
				f.write(response.body)
				f.close()
			captcha = input("please input the captcha\n>")
		else:
			captcha = ''
		return z.json()
这段代码其实就是简单的发送一个验证码的请求,如果你的用户名和密码都正确的话不需要验证码,但是这个请求必须发。

接下来我就把源码贴出来
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值