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 转换 Javascript %u 字符串为python unicode的代码
Sep 06 Python
Python实现读取json文件到excel表
Nov 18 Python
Python实现绘制双柱状图并显示数值功能示例
Jun 23 Python
对python Tkinter Text的用法详解
Oct 11 Python
Python Django的安装配置教程图文详解
Jul 17 Python
Python JSON编解码方式原理详解
Jan 20 Python
Python实现不规则图形填充的思路
Feb 02 Python
Python2.7:使用Pyhook模块监听鼠标键盘事件-获取坐标实例
Mar 14 Python
Python中zip函数如何使用
Jun 04 Python
Python基于正则表达式实现计算器功能
Jul 13 Python
python开发入门——列表生成式
Sep 03 Python
python实现移动木板小游戏
Oct 09 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 遍历显示文件夹下所有目录、所有文件的函数,没有分页的代码
2008/11/14 PHP
PHP对字符串的递增运算分析
2010/08/08 PHP
基于PHP+Ajax实现表单验证的详解
2013/06/25 PHP
php身份证号码检查类实例
2015/06/18 PHP
通过Email发送PHP错误的方法
2015/07/20 PHP
PHP使用preg_split和explode分割textarea存放内容的方法分析
2017/07/03 PHP
jquery 输入框数字限制插件
2009/11/10 Javascript
jquery 分页控件实现代码
2009/11/30 Javascript
jQuery UI Dialog控件中的表单无法正常提交的解决方法
2010/12/19 Javascript
基于JQuery的模拟苹果桌面Dock效果(稳定版)
2012/10/15 Javascript
node.js中的fs.futimes方法使用说明
2014/12/17 Javascript
浅谈JavaScript Date日期和时间对象
2014/12/29 Javascript
jquery实现多屏多图焦点图切换特效的方法
2015/05/04 Javascript
纯js的右下角弹窗实例
2017/03/12 Javascript
JavaScript方法_动力节点Java学院整理
2017/06/28 Javascript
基于bootstrap实现多个下拉框同时搜索功能
2017/07/19 Javascript
详解jQuery中的isPlainObject()使用方法
2018/02/27 jQuery
vue中使用axios post上传头像/图片并实时显示到页面的方法
2018/09/27 Javascript
Node.js 获取微信JS-SDK CONFIG的方法示例
2019/05/21 Javascript
Vue实现渲染数据后控制滚动条位置(推荐)
2019/12/09 Javascript
python去掉行尾的换行符方法
2017/01/04 Python
python下os模块强大的重命名方法renames详解
2017/03/07 Python
python实现电子书翻页小程序
2019/07/23 Python
基于python实现操作git过程代码解析
2020/07/27 Python
学生如何注册Pycharm专业版以及pycharm的安装
2020/09/24 Python
HTML5 视频播放(video),JavaScript控制视频的实例代码
2018/10/08 HTML / CSS
家用个人磨皮机:Trophy Skin
2017/03/30 全球购物
Notino匈牙利:购买香水和化妆品
2019/04/12 全球购物
保卫科工作岗位职责
2014/03/01 职场文书
机关作风建设整改方案
2014/10/27 职场文书
导游词范文
2015/02/13 职场文书
会计专业自荐信范文
2015/03/05 职场文书
暑期家教宣传单
2015/07/14 职场文书
小学毕业感言200字
2015/07/30 职场文书
高中班主任工作总结(范文)
2019/08/20 职场文书
pytorch 如何把图像数据集进行划分成train,test和val
2021/05/31 Python