参考 https://github.com/zkqiang/Zhihu-Login

# -*- coding: utf-8 -*-
import scrapy import time
import re
import base64
import hmac
import hashlib
import json
import matplotlib.pyplot as plt
from PIL import Image class ZhihuSpider(scrapy.Spider):
name = 'zhihu'
allowed_domains = ['www.zhihu.com']
start_urls = ['http://www.zhihu.com/'] login_url = 'https://www.zhihu.com/signup'
login_api = 'https://www.zhihu.com/api/v3/oauth/sign_in'
login_data = {
'client_id': 'c3cef7c66a1843f8b3a9e6a1e3160e20',
'grant_type': 'password',
'source': 'com.zhihu.web',
'username': "+86xxxxxx",
'password': "xxxxxx",
# 传入'cn'是倒立汉字验证码
'lang': 'en',
'ref_source': 'homepage'
}
headers = {
'Connection': 'keep-alive',
'Host': 'www.zhihu.com',
'Referer': 'https://www.zhihu.com/',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
'AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/69.0.3497.100 Safari/537.36'
} def start_requests(self):
if self.login_data["lang"] == 'cn':
api = 'https://www.zhihu.com/api/v3/oauth/captcha?lang=cn'
else:
api = 'https://www.zhihu.com/api/v3/oauth/captcha?lang=en'
yield scrapy.Request(url=api, headers=self.headers, callback=self._is_need_captcha) def _is_need_captcha(self, response):
show_captcha = re.search(r'true', response.text) if show_captcha:
yield scrapy.Request(url=response.url,
headers=self.headers,
method="PUT",
callback=self._get_captcha)
else:
timestamp = str(int(time.time() * 1000))
self.login_data.update({
'captcha': "",
'timestamp': timestamp,
'signature': self._get_signature(timestamp)
})
yield scrapy.FormRequest(
url=self.login_api,
formdata=self.login_data,
headers=self.headers,
callback=self.check_login
) def _get_captcha(self, response):
json_data = json.loads(response.text)
img_base64 = json_data['img_base64'].replace(r'\n', '')
with open('./captcha.jpg', 'wb') as f:
f.write(base64.b64decode(img_base64))
img = Image.open('./captcha.jpg')
if self.login_data["lang"] == 'cn':
plt.imshow(img)
print('点击所有倒立的汉字,按回车提交')
points = plt.ginput(7)
capt = json.dumps({'img_size': [200, 44],
'input_points': [[i[0] / 2, i[1] / 2] for i in points]})
else:
img.show()
capt = input('请输入图片里的验证码:')
# 这里必须先把参数 POST 验证码接口
yield scrapy.FormRequest(url=response.url,
formdata={'input_text': capt},
headers=self.headers,
callback=self.captcha_login,
meta={"captcha":capt}
) def captcha_login(self, response):
timestamp = str(int(time.time() * 1000))
self.login_data.update({
'captcha': response.meta['captcha'],
'timestamp': timestamp,
'signature': self._get_signature(timestamp)
}) yield scrapy.FormRequest(
url=self.login_api,
formdata=self.login_data,
headers=self.headers,
callback=self.check_login
) def check_login(self, response):
yield scrapy.Request(
url=self.login_url,
headers=self.headers,
callback=self.parse
) def _get_signature(self, timestamp):
"""
通过 Hmac 算法计算返回签名
实际是几个固定字符串加时间戳
:param timestamp: 时间戳
:return: 签名
"""
ha = hmac.new(b'd1b964811afb40118a12068ff74a12f4', digestmod=hashlib.sha1)
grant_type = self.login_data['grant_type']
client_id = self.login_data['client_id']
source = self.login_data['source']
ha.update(bytes((grant_type + client_id + source + timestamp), 'utf-8'))
return ha.hexdigest() def parse(self, response):
print(response.text)

scrapy 登陆知乎的更多相关文章

  1. Python爬虫从入门到放弃(二十四)之 Scrapy登录知乎

    因为现在很多网站为了限制爬虫,设置了为只有登录才能看更多的内容,不登录只能看到部分内容,这也是一种反爬虫的手段,所以这个文章通过模拟登录知乎来作为例子,演示如何通过scrapy登录知乎 在通过scra ...

  2. Python之爬虫(二十六) Scrapy登录知乎

    因为现在很多网站为了限制爬虫,设置了为只有登录才能看更多的内容,不登录只能看到部分内容,这也是一种反爬虫的手段,所以这个文章通过模拟登录知乎来作为例子,演示如何通过scrapy登录知乎 在通过scra ...

  3. Python 爬虫模拟登陆知乎

    在之前写过一篇使用python爬虫爬取电影天堂资源的博客,重点是如何解析页面和提高爬虫的效率.由于电影天堂上的资源获取权限是所有人都一样的,所以不需要进行登录验证操作,写完那篇文章后又花了些时间研究了 ...

  4. Python3 使用selenium库登陆知乎并保存cookie为本地文件

    Python3 使用selenium库登陆知乎并保存cookie为本地文件 学习使用selenium库模拟登陆知乎,并将cookie保存为本地文件,然后供以后(requests模块)使用,用selen ...

  5. 第十二篇 requests模拟登陆知乎

    了解http常见状态码 可以通过输入错误的密码来找到登陆知乎的post:url 把Headers拉到底部,可以看到form data _xsrf是需要发送的,需要发送给服务端,否则会返回403错误,提 ...

  6. Scrapy基础(十四)————Scrapy实现知乎模拟登陆

    模拟登陆大体思路见此博文,本篇文章只是将登陆在scrapy中实现而已 之前介绍过通过requests的session 会话模拟登陆:必须是session,涉及到验证码和xsrf的写入cookie验证的 ...

  7. Scrapy 模拟登陆知乎--抓取热点话题

    工具准备 在开始之前,请确保 scrpay 正确安装,手头有一款简洁而强大的浏览器, 若是你有使用 postman 那就更好了.           Python   1 scrapy genspid ...

  8. python模拟登陆知乎并爬取数据

    一些废话 看了一眼上一篇日志的时间 已然是5个月前的事情了 不禁感叹光阴荏苒其实就是我懒 几周前心血来潮想到用爬虫爬些东西 于是先后先重写了以前写过的求绩点代码 爬了草榴贴图,妹子图网,后来想爬婚恋网 ...

  9. 使用OKHttp模拟登陆知乎,兼谈OKHttp中Cookie的使用!

    本文主要是想和大家探讨技术,让大家学会Cookie的使用,切勿做违法之事! 很多Android初学者在刚开始学习的时候,或多或少都想自己搞个应用出来,把自己学的十八般武艺全都用在这个APP上,其实这个 ...

随机推荐

  1. 朱晔的互联网架构实践心得S2E1:业务代码究竟难不难写?

    注意,这是我的架构实践心得的第二季的系列文章,第一季有10篇你也可以回顾. 见https://www.cnblogs.com/lovecindywang/category/1296779.html 最 ...

  2. PHP实用代码片段(三)

    1. 目录清单 使用下面的 PHP 代码片段可以在一个目录中列出所有文件和文件夹. function list_files($dir) { if(is_dir($dir)) { if($handle ...

  3. l^oo不可分的两个注意点

    1  不理解等一个等式 , 2.不理解为什么,一个可分的集合里面有不可数的子集?谢谢 1是 2.是可分集合里面每个元素 做中心后的一个开覆盖 所有0 1序列是和所有二进制小数   可以一一对应   而 ...

  4. 非常详细的Docker学习教程

    一.Docker 简介 Docker 两个主要部件: Docker: 开源的容器虚拟化平台 Docker Hub: 用于分享.管理 Docker 容器的 Docker SaaS 平台 -- Docke ...

  5. 1px实现方案

    JS处理 首先,可以通过 window.devicePixelRatio 拿到设备的像素比,然后给 html 标签加上的相应的样式. function retina () { // 高分辨率屏幕处理 ...

  6. 关于spring的源码的理解

    从最基础的Hello World开始. spring的Hello World就三行代码: public void test() { ApplicationContext context = new C ...

  7. 【学亮IT手记】利用字节流复制文件

  8. Struts2——namespace、action、以及path问题

    简单的介绍下Struts2中的几个简单的问题(namespace.action.以及path问题) namespace(命名空间) Namespace决定了action的访问路径,默认为“”,意味着可 ...

  9. kibana简单使用——elaticsearch的文档,索引的CRUD操作

    1.初始化索引: #number_of_shards:分片的数量,mo'ren默认为5 #number_of_replicas:副本副本的副本的数量 #shards一旦设置不能修改 PUT lagou ...

  10. Java多线程之Join方法阻塞线程

    package org.study2.javabase.ThreadsDemo.status; /** * @Auther:GongXingRui * @Date:2018/9/19 * @Descr ...