Node.JS編程入門58:寫一套反爬蟲系統!

爬蟲,網絡安全最大的威脅之一!

根據爬取數據類型而分,爬蟲有不少種類,比如爬取Email地址的、爬取商品價格的、爬取圖片的,而最多的是爬取內容的,內容數據爬蟲是為氾濫的!

爬蟲讓很多人對其深感苦惱,今天的Node.JS實戰,將實現一種防護性能很強的反爬蟲系統。

Node.JS編程入門58:寫一套反爬蟲系統!

首先展示防護效果,然後付上完整代碼,以瞭解實現方法。

防護效果展示

根據兩個核心思路進行效果展示如下:

1、字體加密

創建自定義字體庫,將字體進行加密。

舉一個最直白的例子:

比如要在網頁中顯示文字:“我是我,你是你,她是她”,在正常的情況下,網頁中就是存在這幾個字,爬蟲當然可以爬取。

我們要實現的效果是,讓這幾個字不存在,網頁源碼中可能是:

Node.JS編程入門58:寫一套反爬蟲系統!

但是在網頁中可以正常顯示:

Node.JS編程入門58:寫一套反爬蟲系統!


但是卻不可複製,複製後,全部或部分內容將不能正常顯示:

Node.JS編程入門58:寫一套反爬蟲系統!

2、字體防破解

單純的字體加密,是不太難被破解的,因為上述的“密文亂碼符號”,其實也就是一種對應關係,例如:“A”對應“啊”,“B”對應“不”。只要獲得足夠的對應關係,替換就可以破解還原出原內容。

具體實施時,可以從網頁中獲取字體文件。

如TTF,通過格式轉換,化為TTX,即可得到對應關係。

也可以手動記錄對應關係。

Node.JS編程入門58:寫一套反爬蟲系統!

那麼對於這兩種破解,我們也需要進行防護。

1、防止字體文件被下載;

動態字體路徑:

注意以下兩圖,不同的字體路徑:

Node.JS編程入門58:寫一套反爬蟲系統!


Node.JS編程入門58:寫一套反爬蟲系統!

即:每次訪問都是不同的字體路徑,而且,此動態路徑文件是不可下載的:

Node.JS編程入門58:寫一套反爬蟲系統!

當然,文件的正常使用是不受影響的。

2、使用動態對應關係,防止字體對應被獲取。

我們內置一套系統,自動或手動實現編碼變化:

以下兩圖,兩種不同的編碼展示,前面部分是編碼,後面是對應的字:

Node.JS編程入門58:寫一套反爬蟲系統!


Node.JS編程入門58:寫一套反爬蟲系統!

源碼展示

實現以上功能的代碼並不複雜,本例由兩個文件,一個目錄組成:

Node.JS編程入門58:寫一套反爬蟲系統!

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

//新的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請求

//urlvar url = req.url;

//首頁訪問if(url == "/"){

url = "./admin/index.html"

}else{

url = "./admin" + url;

}

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

//把變形的url路徑還原回去for(var i=0; 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

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目錄下,是幾個靜態網頁文件:

Node.JS編程入門58:寫一套反爬蟲系統!

index.html內容如下:

anti content splider

原始字體:

變碼字體:

變碼文字:

test.html是用於測試,展示變碼效果的文件,內容如下:

字體測試

@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;

}

Ԕ是Ԕ,ԕ是ԕ,Ԗ是Ԗ,她是她ԛ

ShareWAF(sharewaf.com)不ԗ是WAF!

JS代ԙԘ護?混淆?加密,當然ԚJShaman(jshaman.com)!

以上,是完整的動態字體變碼加密反爬蟲方案,出自於ShareWAF,與ShareWAF運營的商業反爬蟲產品:ShareWAF-ACS,原理甚本一至。由此可知,本文是相當有價值的技術資料。



分享到:


相關文章: