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 open读写文件实现脚本
Sep 06 Python
python使用sorted函数对列表进行排序的方法
Apr 04 Python
Python实现的最近最少使用算法
Jul 10 Python
Django框架下在视图中使用模版的方法
Jul 16 Python
Python按行读取文件的实现方法【小文件和大文件读取】
Sep 19 Python
Python实现连接postgresql数据库的方法分析
Dec 27 Python
python3实现域名查询和whois查询功能
Jun 21 Python
Python操作redis和mongoDB的方法
Dec 19 Python
python3中使用__slots__限定实例属性操作分析
Feb 14 Python
一文轻松掌握python语言命名规范规则
Jun 18 Python
Python 整行读取文本方法并去掉readlines换行\n操作
Sep 03 Python
python munch库的使用解析
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支持断点续传的源码
2010/05/16 PHP
浅谈web上存漏洞及原理分析、防范方法(安全文件上存方法)
2013/06/29 PHP
php实现产品加入购物车功能(1)
2020/07/23 PHP
jquery 插件实现图片延迟加载效果代码
2010/02/06 Javascript
Google Dart编程语法和基本类型学习教程
2013/11/27 Javascript
jquery遍历筛选数组的几种方法和遍历解析json对象
2013/12/13 Javascript
浅谈JavaScript字符集
2014/05/22 Javascript
javascript带回调函数的异步脚本载入方法实例分析
2015/07/02 Javascript
AngularJS实现Model缓存的方式
2016/02/03 Javascript
jQuery实时显示鼠标指针位置和键盘ASCII码
2016/03/28 Javascript
javascript判断图片是否加载完成的方法推荐
2016/05/13 Javascript
深入浅出 jQuery中的事件机制
2016/08/23 Javascript
Vue集成Iframe页面的方法示例
2017/12/12 Javascript
js实现复制功能(多种方法集合)
2018/01/06 Javascript
vue cli webpack中使用sass的方法
2018/02/24 Javascript
Webpack中publicPath路径问题详解
2018/05/03 Javascript
js实现3D照片墙效果
2019/10/28 Javascript
基于JS+HTML实现弹窗提示是否确认提交功能
2020/06/17 Javascript
[01:22:29]真视界:2019年国际邀请赛总决赛
2020/01/29 DOTA
JPype实现在python中调用JAVA的实例
2017/07/19 Python
Python实现合并同一个文件夹下所有txt文件的方法示例
2018/04/26 Python
django缓存配置的几种方法详解
2018/07/16 Python
numpy数组之存取文件的实现示例
2019/05/24 Python
flask应用部署到服务器的方法
2019/07/12 Python
Python如何解除一个装饰器
2020/08/07 Python
纯CSS3实现地球自转实现代码(图文教程附送源码)
2012/12/26 HTML / CSS
关于保护环境的标语
2014/06/09 职场文书
公司年终奖分配方案
2014/06/16 职场文书
12.4法制宣传日标语
2014/10/08 职场文书
2014年酒店年度工作总结
2014/12/10 职场文书
2014年幼儿园德育工作总结
2014/12/17 职场文书
2015年五一劳动节活动总结
2015/02/09 职场文书
小学六一儿童节活动总结
2015/05/05 职场文书
2015年试用期工作总结范文
2015/05/28 职场文书
python 远程执行命令的详细代码
2022/02/15 Python
浅析JavaScript中的变量提升
2022/06/01 Javascript