常见网络爬虫反爬机制与反爬机制的解决方案

反爬

  • 常见反爬
    • 通过User-Agent来反爬
    • 通过Referer来反爬
    • 通过Cookie来反爬
    • 通过js来反爬
    • 通过验证码验证行为来反爬
    • 通过ip地址来反爬
    • 通过自定义字体来反爬
    • 通过css样式来反爬
  • js2py模块的使用
    • js2py简介
    • 简单使用
    • 案例:人人网登录
  • cooike代理池和ip代理池
    • cooike代理池
    • ip代理池

常见反爬

  • 通过User-Agent来反爬
  • 通过Referer来反爬
  • 通过Cookie来反爬
  • 通过js加密请求参数来反爬
  • 通过行为验证来反爬
  • 通过ip地址来反爬
  • 通过自定义字体来反爬
  • 通过css样式来反爬

通过User-Agent来反爬

  • 反爬原理:
    • 爬虫发送请求时,请求头中默认没有User-Agent,或提供非正常的UA
      
  • 应对思路:
    • 在请求时添加UA
      
  • 具体应对:
    • requests模块发送请求时在headers参数中添加UA键值对
      
    • selenium默认自带被控制浏览器的UA,也可以替换UA
      
    • 随机User-Agent,如 faker模块.

通过Referer来反爬

Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的

  • 反爬原理:
    • 爬虫发送请求时,请求头中默认情况下不会带上Referer字段
      
  • 应对思路:
    • 在请求时添加Referer
      
  • 具体应对:
    • requests模块发送请求时在headers参数中添加Referer键值对,从抓包信息中复制Referer信息
      
    • selenium默认自带Referer
      

通过Cookie来反爬

无论是否需要登陆,web服务器都可以在用户的浏览器中设置Cookie;Cookie是header的一部分,当浏览器向web服务器发送请求的时候,如果存在Cookie就一定会携带

  • 反爬原理:
    • web服务器检查请求头中的cookie是否是之前设置的cookie
      
  • 应对思路:
    • 携带cookie发送请求
      
  • 具体应对:
    • requests模块发送请求时,使用requests.session自动处理cookie
      
    • 用requests模块发送请求时,在cookies参数或在headers参数中,使用selenium获取的cookie;注意cookie的过期时间
      
    • 构建cookie池(根据cookie的过期时间,定期批量获取的cookie,放到数据库中),requests模块发送请求时,使用从cookie池中获取的cookie
      

通过js来反爬

很多时候,网站利用用户的浏览器对返回的数据或请求的参数进行解密或加密,比如百度翻译PC版

  • 反爬原理:
    • 利用用户的浏览器执行web服务器返回的js代码来对加密的响应内容进行解密(不常见)
      
    • 利用用户的浏览器执行web服务器返回的js代码来对请求参数进行加密,之后再发送请求(常见)
      
  • 应对思路:
    • python重写js代码的功能、或执行js代码拿到结果
      
  • 具体应对:
    • 完全看不懂js代码:selenium
      
    • 完全看懂js代码:python重写js代码的功能
      
    • 能够看懂js代码执行的大致过程:使用js2py模块运行相关的js代码,获取运行结果(js2py模块在下面将介绍到)
      

通过验证码验证行为来反爬

我们在浏览网站时,经常看见类似12306或者这样的等一些用户行为验证

  • 反爬原理:
    • 对方服务器通过弹出验证码强制验证用户浏览行为
      
  • 应对思路:
    • 使用打码平台或深度学习的方式破解验证码
      
  • 具体应对:
    • 一些打码平台(自己搜索)

通过ip地址来反爬

正常用户很难在很短的时间内打开需要点击才能访问的链接,那么网站就可以根据ip地址和cookie以及user-agent等能区分不同用户身份的信息来进行反爬

  • 反爬原理:
    • 检测同一个ip在单位时间内是否发送了大量请求
      
    • 经常和cookie以及user-agent配合检查
      
  • 应对思路:
    • 网上获取免费的代理ip
      
    • 购买代理ip
      
    • 使用代理ip池
      
  • 具体应对:
    • 构建代理ip池
      
      • 把免费以及收费的代理ip放到数据库中
      • 使用时随机获取一个代理ip
      • 向目标url发送请求,并设置超时
      • 如果超时或无法使用就在数据库中标记该代理ip对具体访问的url不可用
    • requests模块发送请求使用proxies参数
      
    • selenium可以通过配置对象来使用代理ip
      

通过自定义字体来反爬

打开猫眼电影PC页面,右键检查用户评分,查看网页源代码

常见网络爬虫反爬机制与反爬机制的解决方案_第1张图片

  • 反爬原理:
    • 利用浏览器能够加载渲染并正确显示自定义字体的功能,使用自定义字体不影响正常用户浏览
      
  • 应对思路:
    • 从移动端页面获取数据
      
    • 处理并解析自定义字体
      
  • 具体应对:
    • 切换到移动端的页面,如用浏览器移动端模式访问猫眼电影移动端页面
    • 使用fontTools模块来处理猫眼电影的自定义字体文件

通过css样式来反爬

打开去哪儿网PC端页面,搜索并查看飞机票信息

在这里插入图片描述

  • 反爬原理:
    • 利用css样式来便宜标签,且不影响正常用户查看
  • 应对思路:
    • 计算css偏移

js2py模块的使用

当我们仅了解js运行的大致情况,又不能使用selenium的时候,就可以使用js2py来解决js执行和js加密的问题

js2py简介

  • 作用:
    • js2py模块能够帮助我们在python代码中执行js代码,并获取js代码运行的结果或其中的变量
  • 安装:
    • pip install js2py

简单使用

import js2py

js_str = '''
function func(x)
{
    return x
}
'''
# 实例化js解释器对象
js_content = js2py.EvalJs()

js_content.execute(js_str) # 传入并执行js代码
# 调用js代码中的函数并获取返回值
ret = js_content.func('hahaha')
print(ret)

js_var = 'var abc = 1'
js_content.execute(js_var) # # 传入并执行js代码(变量)
# 获取js代码中的变量
print(js_content.abc)

# 向js执行解释器中传入变量
js_content.abc = 2
print(js_content.abc)
  • 步骤:
    • 实例化js解释器对象
      • js_content = js2py.EvalJs()
        
    • 传入并执行js代码
      • js_content.execute(js代码)
        
    • 调用js中的函数并获取返回结果
      • ret = js_content.func('参数')
        
    • 获取js中的变量
      • js_content.变量名
        
    • 向js中传入变量
      • js_content.变量名 = 值
        

案例:人人网登录

利用谷歌浏览器抓包确定登录的url、请求方法以及请求参数

  • url:http://activity.renren.com/livecell/ajax/clog
  • 请求方法:POST
  • 请求体参数:
    • phoneNum: 账号
    • password: 加密之后的密码
    • c1: 0
    • rKey: rkey请求获取的

通过谷歌浏览器抓包知道需要以下三步

  1. 获取rkey
  2. 执行密码加密js
  3. 执行密码加密js过程中会执行BigInt.js 、RSA.js 、Barrett.js 三个js文件
  • 获取rkey

    • url:http://activity.renren.com/livecell/rKey
      
    • 请求方法:GET
      
  • 密码加密js:

t.password = t.password.split("").reverse().join(""),
setMaxDigits(130);
var o = new RSAKeyPair(n.e,"",n.n),
r = encryptedString(o, t.password);
  • 拷贝BigInt.js 、RSA.js 、Barrett.js 三个js文件到本地

参考代码:

import requests
import json
import js2py


#  实例化session对象
session = requests.session()
# 自定义头文件
headers = {
     
    "User-Agent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Mobile Safari/537.36",
    "X-Requested-With": "XMLHttpRequest",
    "Content-Type":"application/x-www-form-urlencoded"
}
# 设置session的请求头信息
session.headers = headers

# 获取js代码中所需要的n值和rKey参数
response = session.get("http://activity.renren.com/livecell/rKey")
# print(response.content.decode())
n = json.loads(response.content)['data']

# 根据获取信息对密码进行加密
# 准备用户名和密码
phoneNum = "131..."
password = "****"

# 使用js2py生成js的执行环境:context
context = js2py.EvalJs()
# 拷贝使用到js文件的内容到本项目中
# 读取js文件的内容,使用context来执行它们
with open("BigInt.js", 'r', encoding='utf8') as f:
    context.execute(f.read())
with open("RSA.js", 'r', encoding='utf8') as f:
    context.execute(f.read())
with open("Barrett.js", 'r', encoding='utf8') as f:
    context.execute(f.read())

# 向context环境中添加需要数据
context.t = {
     'password': password}
context.n = n
# 执行加密密码的js字符
js = '''
       t.password = t.password.split("").reverse().join(""),
       setMaxDigits(130);
       var o = new RSAKeyPair(n.e,"",n.n)
        , r = encryptedString(o, t.password);
      '''
context.execute(js)
# 通过context获取加密后密码信息
# print(context.r)
password = context.r

# 使用session发送登录请求
data = {
     
    'phoneNum': '131....',
    'password': password,
    'c1':0,
    'rKey':n['rkey']
}

response = session.post("http://activity.renren.com/livecell/ajax/clog", data=data)
print(response.content.decode())

# 访问需要登录的资源
response = session.get("http://activity.renren.com/home#profile")
print(response.content.decode())

cooike代理池和ip代理池

cooike代理池

  • cookie池的应用场景
    • 当需要很多账号进行大批量采集数据时,在发送获取数据的请求时都需要登录
    • 或在发送获取数据的请求时都需要发送前置请求
  • cookie池的作用
    • 省资源(减少耗时、减少请求)
    • 保护账号或ip(避免频繁访问)
      常见网络爬虫反爬机制与反爬机制的解决方案_第2张图片
  • 定期获取cookie:可以使用requests模块或selenium
  • 存储cookie
  • 获取cookie的函数或webapi
  • 删除失效cookie的函数或webapi(获取cookie的时间周期可以设置在cookie有效期内)

总结:我们可以不断的去获取cooike然后把这些cookie储存起来,我们要用的时候随机拿一个,如果遇到过期的cooike就把它从储存的地方删除

ip代理池

  • 应用场景:大量代理ip频繁切换时,需要使用代理ip池
  • 作用:提高数据抓取的效率,让服务器以为不是同一个客户端在请求,避免真实ip被封
    常见网络爬虫反爬机制与反爬机制的解决方案_第3张图片
  • 定期获取代理ip:更新存储的代理ip
    • 免费的
    • 收费的
  • 存储代理ip
  • 提供代理ip的接口
  • 删除/标记代理ip的接口
    • 某个经过初步检查(请求下baidu等)代理ip对一个目标url不可用时,不代表对其它域名的url也不好使
    • 这个时候需要在代理ip存储的载体中,标记该代理ip对某个域名无效

总结:我们可以通过一些代理ip网站去获取一些代理ip,然后把这些ip储存起来,我们要用的时候随机拿一个,通过这个ip去访问我们需要爬取的网站,这样可以避免我们使用一个ip频繁访问而被封的情况。

你可能感兴趣的:(python,python)