用NodeJS实现反爬虫,原理&源码放送

栏目: IT技术 · 发布时间: 4年前

内容简介:根据爬取数据类型而分,爬虫有不少种类,比如爬取Email地址的、爬取商品价格的、爬取图片的,而最多的是爬取内容的,内容数据爬虫是为泛滥的!爬虫让很多人对其深感苦恼,今天的Node.JS实战,将实现一种防护性能很强的反爬虫系统。

爬虫,网络安全最大的威胁之一!

根据爬取数据类型而分,爬虫有不少种类,比如爬取Email地址的、爬取商品价格的、爬取图片的,而最多的是爬取内容的,内容数据爬虫是为泛滥的!

爬虫让很多人对其深感苦恼,今天的Node.JS实战,将实现一种防护性能很强的反爬虫系统。

首先展示防护效果,然后付上完整代码,以了解实现方法。

防护效果展示

根据两个核心思路进行效果展示如下:

1、字体加密

创建自定义字体库,将字体进行加密。

举一个最直白的例子:

比如要在网页中显示文字:“我是我,你是你,她是她”,在正常的情况下,网页中就是存在这几个字,爬虫当然可以爬取。

我们要实现的效果是,让这几个字不存在,网页源码中可能是:

用NodeJS实现反爬虫,原理&源码放送

但是在网页中可以正常显示:

用NodeJS实现反爬虫,原理&源码放送

但是却不可复制,复制后,全部或部分内容将不能正常显示:

用NodeJS实现反爬虫,原理&源码放送

2、字体防破解

单纯的字体加密,是不太难被破解的,因为上述的“密文乱码符号”,其实也就是一种对应关系,例如:“A”对应“啊”,“B”对应“不”。只要获得足够的对应关系,替换就可以破解还原出原内容。

具体实施时,可以从网页中获取字体文件。

如TTF,通过格式转换,化为TTX,即可得到对应关系。

也可以手动记录对应关系。

用NodeJS实现反爬虫,原理&源码放送

那么对于这两种破解,我们也需要进行防护。

1、防止字体文件被下载;

动态字体路径:

注意以下两图,不同的字体路径:

用NodeJS实现反爬虫,原理&源码放送

用NodeJS实现反爬虫,原理&源码放送

即:每次访问都是不同的字体路径,而且,此动态路径文件是不可下载的:

用NodeJS实现反爬虫,原理&源码放送

当然,文件的正常使用是不受影响的。

2、使用动态对应关系,防止字体对应被获取。

我们内置一套系统,自动或手动实现编码变化:

以下两图,两种不同的编码展示,前面部分是编码,后面是对应的字:

用NodeJS实现反爬虫,原理&源码放送

用NodeJS实现反爬虫,原理&源码放送

源码展示

实现以上功能的代码并不复杂,本例由两个文件,一个目录组成:

用NodeJS实现反爬虫,原理&源码放送

acs.js是主文件,内容如下:

/**
 * Anti Content Splider
 * Auther:WangLiwen
 * www.ShareWAF.com
 */

var fs = require('fs')
var font_carrier = require("font-carrier")
var body_parser = require("body-parser")
var mime = require("mime");

//变码矩阵,存放字和unicode的对应关系
var transfer_result = require("./config").tramsform_matrix;

/** 
 * TTF变码
 * 基于一种字体,生成另一种新字体
 * 参数:ttf,原始字体
 * 参数:words,要变码的字
 * 参数:new_ttf,新的字体
 * 返回值:新字体中,unicode和字的对应关系 
 */
function transform_ttf(ttf,words,new_ttf){

    //创建新的空字体
    var font = font_carrier.create()

    //从ttf字体中获取文字
    var font_transfer = font_carrier.transfer(ttf)

    if(words.length==0){
        return{};
    }

    var result={};

    var key,value,word;
    //遍历传入的参数:要变码的字体
    for(var i=0;i<words.length;i++){

        //新的unicode
        key="‚"+i;
        //unicode对应的字
        value=words[i];
        //字形
        word=font_transfer.getGlyph(words[i]);

        //加入到新字体中
        font.setGlyph(key,word);

        //输出信息
        result[key]=value;
    }

    //输出各种字体文件
    font.output({
        path:new_ttf
    })

    //返回值
    return result;
}

/**
 * express web
 */
var express = require('express');
var app = express();
app.use(body_parser.urlencoded({extended: true}));

var port = 8000;
var verstion = "0.0.1";
app.listen(port);
console.log("anti content splider");
console.log("v",verstion);
console.log("server at port:",port);
console.log("auther:","wangliwen");
console.log("copyleft","http://www.sharewaf.com");

//变型url特征池,存放要保护的ttf路径,使ttf路径不泄露
var transform_url = [];

//express中间件
app.use(function(req,res,next){

    console.log(req.url,req.method);

    if(req.method.toString().toLowerCase() == "get"){
        //只处理get请求

        //url
        var url = req.url;

        //首页访问
        if(url == "/"){
            url = "./admin/index.html"
        }else{
            url = "./admin" + url;
        }

        //变形url池
        console.log(transform_url);

        //把变形的url路径还原回去
        for(var i=0; i<transform_url.length; i++){

            //当前url,是否包含有变形池中的某条特征内容
            if(url.indexOf(transform_url[i]) != -1){

                //当前时间
                var visit_time = (new Date).getTime();

                //访问时间 - 生成时间变量
                console.log((visit_time - transform_url[i]))

                //超过一定时间访问,视为非法
                //原理:打开html时,会立刻引用页面中引用的ttf,时间间隔不会超过100毫秒
                if((visit_time - transform_url[i]) > 100){
                    res.end("oooops");
                    return;
                }

                //还原路径
                url = url.replace(new RegExp(transform_url[i],"g"), "font_dest");
                console.log("before:",transform_url)

                //删除使用过的时间变量
                delete transform_url[i];
                transform_url.splice(i,1);

                console.log("after:",transform_url)
            }
            
        }

        //真实地址
        console.log("really url:",url);

        //读取文件内容
        var file_content = fs.readFileSync(url)  

        //测试html文件
        if(url.indexOf("/test.html") !=- 1){
            //如果是此html文件,则对文件中的原始字体路径做保护

            //网页源码
            file_content = file_content.toString();

            //遍历变码矩阵,对网页中的文字进行变码
            for (var index in transfer_result){
                console.log(index,transfer_result[index]);
                
                //正则全局替换
                file_content = file_content.replace(new RegExp(transfer_result[index],"g"), index+";");
            }

            
            var count = (file_content.split('font_dest')).length - 1;
            console.log("replaced:",count);

            //以时间做为参照值
            var time_parm = (new Date).getTime();
            //字体路径保护,将正确路径font_dest替换为时间值
            file_content = file_content.replace(new RegExp("font_dest","g"), time_parm);
            
            //存入变型url特征池
            for(var i=0; i<count; i++){
                transform_url.push(time_parm);
            }
                           
        }

        //内容head,写入mime
        res.writeHead(200,{"content-type":mime.getType(url)});
        console.log(url, "mime:", mime.getType(url));

        //内容
        res.write(file_content); 
        
        res.end();  
        
    }else{
        //get之外请求
        next();
    }
})

//post操作
app.post("/transform_ttf",function(req,res){
    console.log(req.body);

    //前端传入的、要变码的字
    var transform_words = req.body.transform_words.toString().split(",");

    //默认变码符号
    transform_words.push("。");

    //源和目标字体目录
    var ttf = "./admin/font_src/" + req.body.font_src;
    var new_ttf = "./admin/font_dest/" + req.body.font_dest;

    //变码结果
    transfer_result = transform_ttf(
        ttf,
        transform_words,
        new_ttf
    );

    console.log(transfer_result);

    //写入文件,给其名称:变码矩阵
    fs.writeFileSync("./config.js","exports.tramsform_matrix="+ JSON.stringify(transfer_result));
    res.send("transform complete!");
});

/**
 * express,结束
 */

代码中已有详细注释。

config.js是字体编码与文字对应关系,源码中称为“变码距阵”,内容如下:

exports.tramsform_matrix={"Ԕ":"我","ԕ":"你","Ԗ":"他","ԗ":"只","Ԙ":"保","ԙ":"码","Ԛ":"用","ԛ":"。"}

注:当进行动态变码操作时,此文件内容会发生变化。

admin目录下,是几个静态网页文件:

用NodeJS实现反爬虫,原理&源码放送

index.html内容如下:

<html>
    <head>
        <meta charset="utf8">
        <title>anti content splider</title>
    </head>
    <body>
        <form method="post" action="/transform_ttf" target="_blank">
            原始字体:<input id="font_src" name="font_src" type="text" value="KaiGenGothicSC-Normal.ttf" /><br>
            变码字体:<input id="font_dest" name="font_dest" type="text" value="font1" /><br>
            变码文字:<input id="transform_words" name="transform_words" type="text" value="我,你,他,只,保,码,用" /><br>
            <br>
            <input type="submit" value="Transform!"/>
        </form>
    </body>
</html>

test.html是用于测试,展示变码效果的文件,内容如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>字体测试</title>
</head>
<body>
<div>
<style>
  @font-face {
    font-family: "font1";
    src: url("font_dest/font1.eot"); /* IE9 */
    src: url("font_dest/font1.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */
    url("font_dest/font1.woff2") format("woff2"),
    url("font_dest/font1.woff") format("woff"),
    url("font_dest/font1.ttf") format("truetype"), /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/
    url("font_dest/font1.svg#iconfont"); /* iOS 4.1- */
  }
  .font-1{
    font-family:"font1";font-size:16px;font-style:normal;
  }
</style>
  <div>Ԕ是Ԕ,ԕ是ԕ,Ԗ是Ԗ,她是她ԛ</div>
  <div>ShareWAF(sharewaf.com)不ԗ是WAF!</div>
  <div>JS代ԙԘ护?混淆?加密,当然ԚJShaman(jshaman.com)!</div>
</div>
</body>
</html>

用NodeJS实现反爬虫,原理&源码放送


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

JavaScript and Ajax for the Web, Sixth Edition

JavaScript and Ajax for the Web, Sixth Edition

Tom Negrino、Dori Smith / Peachpit Press / August 28, 2006 / $24.99

Book Description Need to learn JavaScript fast? This best-selling reference’s visual format and step-by-step, task-based instructions will have you up and running with JavaScript in no time. In thi......一起来看看 《JavaScript and Ajax for the Web, Sixth Edition》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

URL 编码/解码
URL 编码/解码

URL 编码/解码