django 反爬实践与反反爬攻略,request甄别、接口加密、redis限频、字体反爬 ... ...

写在前面

前段时间想着做一个关于反爬的小活动,目前已经做完了,整理了用到的一些反爬。本文所述代码均已上传至 github https://github.com/yejue/thegame2


JS断点

JS断点是一个用于debugger的断点语句,在全局设置无限的断点,在爬虫尝试打开开发者工具查看前端源码的时候激活,使得前端页面暂停,有一定的阻挡效果。

使用方法:

// 在全局JS中设置周期循环调用 debugger
setInterval(function(){
    
    debugger}, 1000);

解决方法:

点击如图所示 Deactivate breakpoints 或者快捷键 Ctrl + F8 取消断点,再次点击运行按钮即可。

在这里插入图片描述

JS防Selenium

window对象对应着整一个打开的窗口,也可以说是当前的浏览器整体,搞清楚标签页就大概清楚了。可以在控制台中打印window对象,将selenium与正常浏览器做对比,寻找到差异。比较靠谱的差异是在 navigator中的webdriver,凡是selenium这个属性值都为true,正常的则 undefined。
在这里插入图片描述
使用方法:页面加载时对该属性进行判断,再决定做什么动作。

解决方法:这是一个旧版的基于开发这模式的解决方式,options = webdriver.ChromeOptions() …应该是没效了。此处分享一个新的解决博文。https://www.cnblogs.com/presleyren/p/12936553.html

auth系统、session加密

这是基本操作,没多大反爬意图。

auth系统是django自带的一个身份认证系统,使用其中的登录认证装饰器来便捷确保需要登录才能看到核心页面。

from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator

@method_decorator(login_required, name='get')
class SpiderDataListView(View):
	pass

session加点密,只需要在settings更换session引擎即可,多多少少影响观感。

SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'

request 请求甄别

一个request请求中有这些东西,其中需要关注的是 META 和 headers。

```

META包含了headers,是完整的请求信息,分别使用浏览器和爬虫访问,将取得的请求信息放到notepad++ 中做个对比,会发现请求上的不一样。但实际上META中有差异的部分基本上来自于其中的headers,所以在使用时建议使用headers进行鉴别会更加简洁明了。以下是最时常有差异的几个请求键

User-Agent, Accept, Accept-Language, Referer

使用方法:

  1. UserAgent: 判断 python、curl、java、w3m等关键字是否在里面,是则 do something…
  2. Accept: 一开始只有你和请求知道会接收什么东西,譬如 text/html,application/xhtml+xml,
    application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9
  3. Accept-Language: 爬虫默认是不指定语言的
  4. Referer: 描述来自于哪一页,非期待的页面则 do someting …

解决办法:复制一个正常访问的headers 基本可以解决,若不能再查找遗漏。

接口加密

保护接口,返回一个解密过的字符串,例如简单的使用 ord 对 unicode 值做偏移,加减乘除,一次函数,二次函数等等… … 使用后返回到前端的数值由 JS 来反向解密。

使用方法:

一个对 unicode 值 +2 的小例子

def hanshu(s: str):
    return ''.join([chr(i2) for i2 in [ord(i)+2 for i in s]])
string1 = 'xx'			// 一个接收到的加密字符串
string = ''  			// 一个空的字符串
for(let i=0;i<string1.length;i++){
    
    
    string2 += String.fromCharCode(string1.charAt(i).charCodeAt()-2);
}

解决方法:找规律,或者看 JS 源码

JS 混淆

像上面那个情况,为了不被别人很简单的发现规律,对JS进行混淆压缩,变得很难看。

使用方法:站长工具有一个混淆压缩工具,混淆即可
解决方法:同样的复制混淆过的到工具中,解密即可

redis 访问频率

redis是一个运行在内存的nosql数据库,使用redis比一般数据库快特别多,传输延迟可以忽略不计,实时记录访问频率是不错的选择。

使用方法:

1 在caches中设置需要使用的库名和别名

CACHES = {
    
    
    'request_interval': {
    
    
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': [
            'redis://127.0.0.1:6379/3'
        ],
        'option': {
    
    
            'CLIENT_CLASS': 'django_redis.client.DefaultClient'
        }
    }
}

2 每一个访问使用一个标志记录在redis中,可以使用用户 ip (在META中取得)

from django_redis import get_redis_connection

# 连接
redis_conn = get_redis_connection(alias='request_interval')
req_flag_key = 'req_flag_{}'.format(ip)
# 让管道通知redis
pl = redis_conn.pipeline()
# 设置生存时间与value 2s,默认值为 1
pl.setex(req_flag_key, 2, 1)

3 在请求进来时判断 req_flag_key 是否存在,是则 do something

redis_conn = get_redis_connection(alias='request_interval')
if redis_conn.get('req_flag_{}'.format(ip)):
	do something ...
    return HttpResponse('', status=418)

字体反爬

在网站中,我们只需要保证正常人看到的信息是正常的即可,所以在保证前端显示一致的情况下,源码可以是任何东西。字体反爬即是如此,前端显示的是一回事,源码显示的又是另一回事。
在这里插入图片描述
使用方法:

1 下载一个字体编辑工具,例如 FontCreator
2 打开一个字体,使用其他的图片代替关键的字,可以复制其他字形到覆盖上去,如下图是将 !覆盖到了3、4、5、6 的位置,那么在前端中,这几个数字将显示为 !
在这里插入图片描述
3 前端引用字体。至于要怎么样随机字体,就看个人需求了。

@font-face {
    
    
    font-family: 'Arial g';
    src: url("{% static 'fonts/arial.ttf' %}");
}

xxx {
    
    font-family: 'Arial g'}

解决方法:查看对应的字体,下载,同样使用字体编辑工具打开,找到对应 unicode 值的真实值即可。


我是庸了个白,你的点赞将是我更新的最大动力

猜你喜欢

转载自blog.csdn.net/qq_39177678/article/details/108897326