- 写在前面
- JS断点
- JS防Selenium
- auth系统、session加密
- request 请求甄别
- 接口加密
- JS 混淆
- 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
使用方法:
- UserAgent: 判断 python、curl、java、w3m等关键字是否在里面,是则 do something…
- 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 - Accept-Language: 爬虫默认是不指定语言的
- 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' // 一个接收到的加密字符串
string2 = '' // 一个空的字符串
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 值的真实值即可。
我是庸了个白,你的点赞将是我更新的最大动力