#-*-coding:utf-8 -*-
__author__ = "ruoniao"
__date__ = "2017/5/31 20:59"

之前我们通过爬取伯乐在线的文章,伯乐在线对爬取没有什么限制,这次爬取知乎,就有了爬取限制,首先就是
登录限制;为破解限制,首先就是模拟登录

模拟登陆首先要明白的就是session和cookie机制:

简单的说(个人理解):
  http是一种无状态的协议,为解决用户每次都需要输入密码登录的烦恼,也为了服务器能够记住每次请求的浏览器,就有了会话机制,

就是每次对话不需要问你是谁,浏览器只需要将服务器原先发送给浏览器的ID原封不动的还给服务器,这样服务器就可以在自己的
数据库中查找这个ID就可以,而只有这个ID是没用的,若想要用户登录,还需要用用户名和密码,加密后以cookie的形式存储在本地,

下次请求直接发送给服务器就行

总之:为了服务器和浏览器之间互相确认身份,服务器生成一个session_id并且保存在服务器,还有给浏览器一份,浏览器将这个session_id写入cookie,

发送给服务器,服务器对照自己保存在本地的,就能互相确认身份;不同的是:cookie中还带了用户的个人信息等

    
        cookie是存储在本地的记录某个网站的个人信息的机制
        session是存储在服务器中的记录某个浏览器(用户)的信息的机制,更安全;
具体理解可参考这篇文章

不同的网站模拟登录的策略不同,不同的网站要进行不同的分析;但都是大同小异;做过web的明白,无非就是用户的验证;较难的就是识别验证码了

知乎的登录破解:

1:这里遇到了坑,因为在firebug中测试时,post到url时没有填写验证码;而通过requests post到URL
   具体参数时报错:验证码错误,这就很纳闷了;
    2:原来:当向首页get时,因为有cookies,所以登录时就不需要填写验证码;通过代码时没有加cookies,需要填写验证码
    而验证码不好识别,只能更换思路
    3: 模拟浏览器的行为,若当初为取的xsrf时get带上cookie,下次登录就不需要验证码了
    4:那么怎么才能将cookie post到URL呢?了解requests.post()方法的知道:post()可带的参数很多
    其中cookies= {}或CookieJar
    5:将cookies以字典的形式post方便操作,只需要在firebug中的cookies复制为字典的格式
       以CookieJar的形式:因为cookie是保存在硬盘的,可以参考这篇博文

6:因为cookie是有生存周期的额,为了下面重新登录,可以将登录后的cookie以txt的形式保存在本地,下次直接load就可以

实例代码注释

 import requests
#适合python2和python3版本的导包
try:
import cookielib
except:
import http.cookiejar as cookielib
import re
from urllib import parse, request #使用会话机制向url发送request,提高效率,不必每次都发请求(类比浏览器直接在本标签页操作,不需重新产生新的标签页)
session = requests.session()
#将会话产生的cookies保存在本地
session.cookies = cookielib.LWPCookieJar(filename="cookies.txt") #浏览器版本信息,目的是伪装成一个浏览器,让服务器认为我们的代码是一个浏览器请求而不是爬虫,避免被拒绝
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0",
"Host":"www.zhihu.com",
"Referer":"https://www.zhihu.com/",
} #获取登录xsrf
def get_xsrf(): url = "https://www.zhihu.com/#signin" try:
#带上cookie,避免产生验证码识别
req = session.get(url=url,cookies=cookies,headers=headers)
#通过正则表达式解析出 xsrf 类比csrf机制
xsrf = re.findall('<input type="hidden" name="_xsrf" value="(.*?)"/>',req.text)
if xsrf:
xsrf = xsrf[0]
print(xsrf)
return xsrf
else:
return xsrf
except Exception as e:
print(e)
print("failed download") #知乎登录
def zhihu_login(account,password): #首先获取xsrf
xsrf = get_xsrf()
#判断是手机号:以手机号登录,提交表单和提交URL不同,构造不同的URL和表单
if re.match("\d{10}",account): url = "https://www.zhihu.com/login/phone_num"
data={
"_xsrf":xsrf,
'remember_me': 'true',
"password":password,
"phone_num":account
}
if '@' in account:
url = "https://www.zhihu.com/login/email"
data={
"_xsrf":xsrf,
'remember_me': 'true',
"password":password,
"email":account
}
#将获取到的xsrf加载到cookie中
cookies["_xsrf"] = xsrf
#带上表单,头信息,cookies申请登录
r = session.post(url=url,data=data,headers=headers,cookies=cookies)
print(r.text)
#登录成功将cookies保存到本地
session.cookies.save() #获取首页;登录后可直接获取,因为session中已经(带了)加载了cookie
def get_index():
response = session.get("https://www.zhihu.com/",headers=headers)
print(response.status_code)
#将首页写入本地文件
with open("index_page.html","wb") as f:
f.write(response.text.encode("utf-8"))
print("write ok") #查看登录状态;向一个只有登录的页面get,若登录会返回200;否则304,会重定向到登录页(重定向后会返回200)
def is_login():
url = "https://www.zhihu.com/inbox"
#allow_redirects 禁止重定向
response = session.get(url=url,headers=headers,allow_redirects=False)
#判断是否登录
if response.status_code != 200:
return False
else:
return True #先尝试本地cookie登录,不成功使用浏览器copy下来的cookies重新登录,生成本地cookies
try:
#先尝试加载之前保存在本地的cookies
session.cookies.load(ignore_discard=True)
print("cookies 已记载")
except:
#没加载就重新登录
print("cookie 未加载")
#这个cookie是从firebug中复制来的
cookies = {
"d_c0":"",
"l_cap_id":"",
"r_cap_id":"",
"cap_id":"",
"_zap":"",
"__utmc":"",
"__utmb":"",
"__utmv":"",
"__utma":"",
"__utmz":"",
"q_c1":""
}
#调用登录函数,成功后会更新cookie到本地
zhihu_login("342200377@qq.com","")
#更新成功后重新加载cookies
session.cookies.load(ignore_discard=True) print(is_login())

Scrapy基础(十四)————知乎模拟登陆的更多相关文章

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

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

  2. Bootstrap<基础十四> 按钮下拉菜单

    使用 Bootstrap class 向按钮添加下拉菜单.如需向按钮添加下拉菜单,只需要简单地在在一个 .btn-group 中放置按钮和下拉菜单即可.也可以使用 <span class=&qu ...

  3. Python爬虫实例(四)网站模拟登陆

    一.获取一个有登录信息的Cookie模拟登陆 下面以人人网为例,首先使用自己的账号和密码在浏览器登录,然后通过抓包拿到cookie,再将cookie放到请求之中发送请求即可,具体代码如下: # -*- ...

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

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

  5. C++学习基础十四——基础类型vector

    一.vector的使用 1. #include <vector> 2. 初始化的四种方法 vector<T> v1; vector<T> v2(v1); vecto ...

  6. Java基础(十四)--装箱、拆箱详解

    Java中基本数据类型都有相对应的包装类 什么是装箱?什么是拆箱? 在Java SE5之前,Integer是这样初始化的 Integer i = new Integer(10); 而在从Java SE ...

  7. java基础(十四)-----详解匿名内部类——Java高级开发必须懂的

    在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意的事项.匿名内部类使用的形参为何要为final. 使用匿名内部类内部类 匿名内部类由于没有名字,所以它的创建方式有点儿奇怪.创建格式如下: n ...

  8. Scrapy基础(十二)————异步导出Item数据到Mysql中

    异步导出数据到Mysql中 上次说过从Item中同步写入数据库,因为网络的下载速度和数据库的I/O速度是不一样的所以有可能会发生下载快,但是写入数据库速度慢,造成线程的堵塞:关于堵塞和非堵塞,同步和异 ...

  9. Scrapy基础(十)———同步机制将Item中的数据写在Mysql

      前面讲解到将Item中的所有字段都已经填写完成,那么接下来就是将他们存储到mysql数据库中,那就用到了pipeline项目管道了:  对项目管道的理解:做一个比喻,爬取好比是开采石油,Item装 ...

随机推荐

  1. ZooKeeper-集群模式安装

    下载地址:https://zookeeper.apache.org/releases.html 至少需要准备三台节点(这里为h136.h138.h140),ZooKeeper 需要 JDK,关于 JD ...

  2. DirectX11 With Windows SDK--13 动手实现一个简易Effects框架、阴影效果绘制

    前言 到现在为止,所有的教程项目都没有使用Effects11框架类来管理资源.因为在D3DCompile API (#47)版本中,如果你尝试编译fx_5_0的效果文件,会收到这样的警告: X4717 ...

  3. Python复习笔记(十一)TCP/IP协议

    1. TCP/IP协议简介 帧头: mac地址, 网卡上的序列号 2. wireshark使用 分析一个数据是否发送, 是否是网络问题 ip.dst == 192.168.0.137 and udp ...

  4. Elasticsearch-基础介绍及索引原理分析(转载)

    最近在参与一个基于Elasticsearch作为底层数据框架提供大数据量(亿级)的实时统计查询的方案设计工作,花了些时间学习Elasticsearch的基础理论知识,整理了一下,希望能对Elastic ...

  5. IIS版本号可以被识别 解决方案

    1.在IIS配置文件中进行修改. 借助IIS URL Rewrite Module,添加如下的重写规则: <rewrite> <allowedServerVariables> ...

  6. oldboy s21day11

    #!/usr/bin/env python# -*- coding:utf-8 -*- # 1.列举 str.list.dict.set 中的常用方法(每种至少5个),并标注是否有返回值.'''str ...

  7. js文件上传原理(form表单 ,FormData + XHR2 + FileReader + canvas)

    目录 form表单上传 FormData + XHR2 + FileReader + canvas 无刷新本地预览压缩上传实例 目前实现上传的方式 浏览器小于等于IE9(低版本浏览器)使用下面的方式实 ...

  8. css长度单位学习(em,rem,px,vw,vh)

    绝对长度单位 绝对长度单位代表一个物理测量 [像素px(pixels)] 像素,为影像显示的基本单位,译自英文"pixel",pix是英语单词picture的常用简写,加上英语单词 ...

  9. SpringBoot之解决云服务器VPS在所处云端集群的内网不能解析域名的问题:java.net.UnknownHostException:abc.cn: Temporary failure in name resolution

    一.起因与原因分析过程 前端小伙伴儿告诉我,说服务器崩了. 请求数据接口,接口有响应,但报的json提示指向:数据库异常错误. 遂登陆云主机查看日志,核心记录显示如下: 2018-11-09 22:1 ...

  10. Existing lock /var/run/yum.pid: another copy is running as pid 解决办法

    yum只能支持一个例程运行,所以如果有一个例程已经在运行,其他的必须等待该进程退出释放lock.出现这种情况时,可以用以下命令来恢复: rm -f /var/run/yum.pid