参考 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. python2中reload(sys)后设置编码

    python在安装时,默认的编码是ascii,当程序中出现非ascii编码时,python的处理常常会报这样的错UnicodeDecodeError: 'ascii' codec can't deco ...

  2. 二维数组中的查找问题--剑指offer面试题3

    题目:在一个二维数组中,对每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. // 二维数组中的查找 ...

  3. 【问题解决方案】Dev C++ 无法调试的问题与解决

    听翁恺老师课的时候用到一个叫DevC++的编辑器. 学到调试部分的时候,老师的没问题我的报错.我?? 试一试网上查到的方法: 工具 --> 编译选项 --> 代码生成/优化 --> ...

  4. jQuery学习(监听DOM加载)

    jQuery的extend方法 function njQuery() { } /* njQuery.extend = function (obj) { // 此时此刻的this就是njQuery这个类 ...

  5. mybatis源码分析(四)---------------代理对象的生成

    在mybatis两种开发方式这边文章中,我们提到了Mapper动态代理开发这种方式,现在抛出一个问题:通过sqlSession.getMapper(XXXMapper.class)来获取代理对象的过程 ...

  6. bootstrap模态框modal使用remote动态加载内容,第二次加载显示相同内容解决办法

    bootstrap的modal中,使用remote可以动态加载页面到modal-body中,并弹窗显示 如果提供的是 URL,将利用 jQuery 的 load 方法从此 URL 地址加载要展示的内容 ...

  7. Angular 基本指令

    <!DOCTYPE html><html ng-app><head lang="en"> <meta charset="UTF- ...

  8. linux安装httpd,做文件服务器

    在一个团队或者公司层面上,做一个本地的文件服务器,将网上的资源下载到本地,是有必要的.这将节省其他人的很多下载时间. >>提君博客原创  http://www.cnblogs.com/ti ...

  9. js获取数组中相同元素数量

    <script> var array = new Array(1,2,5,1,4,4,2,3,5,1,1,5,5,5,6,7,3,9,9,10); var arr = new Array( ...

  10. Vue 刷新当前页面,并重新加载页面数据

    业务场景:在管理后台,在执行完,增,删,改,操作的时候.我们需要刷新一下页面,重载数据.在JQ中我们会用到location.reload()方法,刷新页面:在vue中,这里需要用到一个 provide ...