Python爬虫之模拟知乎登录的方法教程


Posted in Python onMay 25, 2017

前言

对于经常写爬虫的大家都知道,有些页面在登录之前是被禁止抓取的,比如知乎的话题页面就要求用户登录才能访问,而 “登录” 离不开 HTTP 中的 Cookie 技术。

登录原理

Cookie 的原理非常简单,因为 HTTP 是一种无状态的协议,因此为了在无状态的 HTTP 协议之上维护会话(session)状态,让服务器知道当前是和哪个客户在打交道,Cookie 技术出现了 ,Cookie 相当于是服务端分配给客户端的一个标识。

Python爬虫之模拟知乎登录的方法教程

  • 浏览器第一次发起 HTTP 请求时,没有携带任何 Cookie 信息
  • 服务器把 HTTP 响应,同时还有一个 Cookie 信息,一起返回给浏览器
  • 浏览器第二次请求就把服务器返回的 Cookie 信息一起发送给服务器
  • 服务器收到HTTP请求,发现请求头中有Cookie字段, 便知道之前就和这个用户打过交道了。

实战应用

用过知乎的都知道,只要提供用户名和密码以及验证码之后即可登录。当然,这只是我们眼中看到的现象。而背后隐藏的技术细节就需要借助浏览器来挖掘了。现在我们就用 Chrome 来查看当我们填完表单后,究竟发生了什么?

Python爬虫之模拟知乎登录的方法教程

(如果已经登录的,先退出)首先进入知乎的登录页面 https://www.zhihu.com/#signin ,打开 Chrome 的开发者工具条(按 F12)先尝试输入一个错误的验证码观察浏览器是如何发送请求的。

Python爬虫之模拟知乎登录的方法教程

从浏览器的请求可以发现几个关键的信息

  • 登录的 URL 地址是 https://www.zhihu.com/login/email
  • 登录需要提供的表单数据有4个:用户名(email)、密码(password)、验证码(captcha)、_xsrf。
  • 获取验证码的URL地址是 https://www.zhihu.com/captcha.gif?r=1490690391695&type=login

_xsrf 是什么?如果你对CSRF(跨站请求伪造)攻击非常熟悉的话,那么你一定知道它的作用,xsrf是一串伪随机数,它是用于防止跨站请求伪造的。它一般存在网页的 form 表单标签中,为了证实这一点,可以在页面上搜索 “xsrf”,果然,_xsrf在一个隐藏的 input 标签中

Python爬虫之模拟知乎登录的方法教程

摸清了浏览器登录时所需要的数据是如何获取之后,那么现在就可以开始写代码用 Python 模拟浏览器来登录了。登录时所依赖的两个第三方库是 requests 和 BeautifulSoup,先安装

pip install beautifulsoup4==4.5.3
pip install requests==2.13.0

http.cookiejar 模块可用于自动处理HTTP Cookie,LWPCookieJar 对象就是对 cookies 的封装,它支持把 cookies 保存到文件以及从文件中加载。

而 session 对象 提供了 Cookie 的持久化,连接池功能,可以通过 session 对象发送请求

首先从cookies.txt 文件中加载 cookie信息,因为首次运行还没有cookie,所有会出现 LoadError 异常。

from http import cookiejar
session = requests.session()
session.cookies = cookiejar.LWPCookieJar(filename='cookies.txt')
try:
 session.cookies.load(ignore_discard=True)
except LoadError:
 print("load cookies failed")

获取 xsrf

前面已经找到了 xsrf 所在的标签,,利用 BeatifulSoup 的 find 方法可以非常便捷的获取该值

def get_xsrf():
 response = session.get("https://www.zhihu.com", headers=headers)
 soup = BeautifulSoup(response.content, "html.parser")
 xsrf = soup.find('input', attrs={"name": "_xsrf"}).get("value")
 return xsrf

获取验证码

验证码是通过 /captcha.gif 接口返回的,这里我们把验证码图片下载保存到当前目录,由人工识别,当然你可以用第三方支持库来自动识别,比如 pytesser。

def get_captcha():
 """
 把验证码图片保存到当前目录,手动识别验证码
 :return:
 """
 t = str(int(time.time() * 1000))
 captcha_url = 'https://www.zhihu.com/captcha.gif?r=' + t + "&type=login"
 r = session.get(captcha_url, headers=headers)
 with open('captcha.jpg', 'wb') as f:
  f.write(r.content)
 captcha = input("验证码:")
 return captcha

登录

一切参数准备就绪之后,就可以请求登录接口了。

def login(email, password):
 login_url = 'https://www.zhihu.com/login/email'
 data = {
  'email': email,
  'password': password,
  '_xsrf': get_xsrf(),
  "captcha": get_captcha(),
  'remember_me': 'true'}
 response = session.post(login_url, data=data, headers=headers)
 login_code = response.json()
 print(login_code['msg'])
 for i in session.cookies:
  print(i)
 session.cookies.save()

请求成功后,session 会自动把 服务端的返回的cookie 信息填充到 session.cookies 对象中,下次请求时,客户端就可以自动携带这些cookie去访问那些需要登录的页面了。

auto_login.py 示例代码

# encoding: utf-8
# !/usr/bin/env python
"""
作者:liuzhijun
"""
import time
from http import cookiejar

import requests
from bs4 import BeautifulSoup

headers = {
  "Host": "www.zhihu.com",
  "Referer": "https://www.zhihu.com/",
  'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87'
}

# 使用登录cookie信息
session = requests.session()
session.cookies = cookiejar.LWPCookieJar(filename='cookies.txt')
try:
  print(session.cookies)
  session.cookies.load(ignore_discard=True)

except:
  print("还没有cookie信息")


def get_xsrf():
  response = session.get("https://www.zhihu.com", headers=headers)
  soup = BeautifulSoup(response.content, "html.parser")
  xsrf = soup.find('input', attrs={"name": "_xsrf"}).get("value")
  return xsrf


def get_captcha():
  """
  把验证码图片保存到当前目录,手动识别验证码
  :return:
  """
  t = str(int(time.time() * 1000))
  captcha_url = 'https://www.zhihu.com/captcha.gif?r=' + t + "&type=login"
  r = session.get(captcha_url, headers=headers)
  with open('captcha.jpg', 'wb') as f:
    f.write(r.content)
  captcha = input("验证码:")
  return captcha


def login(email, password):
  login_url = 'https://www.zhihu.com/login/email'
  data = {
    'email': email,
    'password': password,
    '_xsrf': get_xsrf(),
    "captcha": get_captcha(),
    'remember_me': 'true'}
  response = session.post(login_url, data=data, headers=headers)
  login_code = response.json()
  print(login_code['msg'])
  for i in session.cookies:
    print(i)
  session.cookies.save()


if __name__ == '__main__':
  email = "xxxx"
  password = "xxxxx"
  login(email, password)

github源码地址:https://github.com/lzjun567/crawler_html2pdf/blob/master/zhihu/auto_login.py

总结

以上就是关于Python爬虫之模拟知乎登录的全部内容,希望本文的内容对大家学习或者使用python能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
python获取一组汉字拼音首字母的方法
Jul 01 Python
Python PyQt5标准对话框用法示例
Aug 23 Python
2018年Python值得关注的开源库、工具和开发者(总结篇)
Jan 04 Python
对python中使用requests模块参数编码的不同处理方法
May 18 Python
利用Pandas读取文件路径或文件名称包含中文的csv文件方法
Jul 04 Python
对pandas写入读取h5文件的方法详解
Dec 28 Python
Python面向对象程序设计类变量与成员变量、类方法与成员方法用法分析
Apr 12 Python
在win10和linux上分别安装Python虚拟环境的方法步骤
May 09 Python
Python3安装psycopy2以及遇到问题解决方法
Jul 03 Python
在Tensorflow中实现leakyRelu操作详解(高效)
Jun 30 Python
python如何实现递归转非递归
Feb 25 Python
详解NumPy中的线性关系与数据修剪压缩
May 25 Python
python爬虫入门教程--优雅的HTTP库requests(二)
May 25 #Python
Python操作使用MySQL数据库的实例代码
May 25 #Python
python爬虫入门教程--快速理解HTTP协议(一)
May 25 #Python
用生成器来改写直接返回列表的函数方法
May 25 #Python
Python随机读取文件实现实例
May 25 #Python
利用Anaconda完美解决Python 2与python 3的共存问题
May 25 #Python
Python实现的简单dns查询功能示例
May 24 #Python
You might like
php上的memcache和memcached两个pecl库
2010/03/29 PHP
php 连接mysql连接被重置的解决方法
2011/02/15 PHP
for循环连续求和、九九乘法表代码
2012/02/20 PHP
thinkphp中html:list标签传递多个参数实例
2014/10/30 PHP
完美实现wordpress禁止文章修订和自动保存的方法
2014/11/03 PHP
php中引用符号(&)的使用详细介绍
2016/12/06 PHP
浅谈php的TS和NTS的区别
2019/03/13 PHP
php如何实现数据库的备份和恢复
2020/11/30 PHP
js导出table到excel同时兼容FF和IE示例
2013/09/03 Javascript
Javascript中string转date示例代码
2013/11/01 Javascript
jquery选择器需要注意的问题
2014/11/26 Javascript
JS实现iframe自适应高度的方法(兼容IE与FireFox)
2016/06/24 Javascript
AngularJS入门教程之ng-class 指令用法
2016/08/01 Javascript
js实现三级联动效果(简单易懂)
2017/03/27 Javascript
node.js+jQuery实现用户登录注册AJAX交互
2017/04/28 jQuery
vue给组件传递不同的值方法
2018/09/29 Javascript
js实现图片放大并跟随鼠标移动特效
2019/01/18 Javascript
可能被忽略的一些JavaScript数组方法细节
2019/02/28 Javascript
vue实现随机验证码功能(完整代码)
2019/12/10 Javascript
Python中几种操作字符串的方法的介绍
2015/04/09 Python
Python图像灰度变换及图像数组操作
2016/01/27 Python
基于python实现百度翻译功能
2019/05/09 Python
cProfile Python性能分析工具使用详解
2019/07/22 Python
Python版中国省市经纬度
2020/02/11 Python
Python第三方包之DingDingBot钉钉机器人
2020/04/09 Python
CSS3制作炫酷的下拉菜单及弹起式选单的实例分享
2016/05/17 HTML / CSS
html5给汉字加拼音加进度条的实现代码
2020/04/07 HTML / CSS
html5 canvas 实现光线沿不规则路径运动
2020/04/20 HTML / CSS
荟萃全球保健品:维他购
2018/05/09 全球购物
如何写一封打动人心的求职信
2014/02/17 职场文书
团结就是力量演讲稿
2014/05/21 职场文书
大一新生期末自我评价
2014/09/12 职场文书
2014年酒店工作总结范文
2014/11/17 职场文书
论文致谢词范文
2015/05/14 职场文书
redis不能访问本机真实ip地址的解决方案
2021/07/07 Redis
node.js使用express-fileupload中间件实现文件上传
2021/07/16 Javascript