内容简介:细心的人会问,为什么不把所有的内容都替换成编码呢?这个就涉及到加载和渲染速度的问题。还有如果启动字体反爬虫,基本上已经告别SEO了,请仔细考虑中间的厉害关系,你懂得!我们知道,单纯汉字就有好几千个,还有各种字符,有的还包含各种外国人的字符串!如果全部放到自定义字体库中的话,这个文件灰常大,几十兆是肯定有的了,那后果啥样就很清楚了,加载肯定很慢,更糟糕的是如此之多的字体需要浏览器去渲染,那效果,卡到爆!!!为了解决这个问题,我们可以选择只渲染少量的、部分的文字,假设50个字,那么字体库就会小到几十K了,相当于
0x0 前言
反爬虫和爬虫之间的较量已经争斗多年,不管是攻还是守,已经持续N年,这是一个没有硝烟的战场,大家都知道爬虫和反爬之家的道高一尺魔高一丈的关系。但这个方案可以很大程度上可以增加普通爬虫的采集成本,在不使用OCR的前提下,算是比较极致的方案了。当然方案有很多种,层出不穷的各种方法,这里介绍的时候反爬虫的中的一种比较实用的方案,字体反爬也就是自定义字体反爬通过调用自定义的ttf文件来渲染网页中的文字,而网页中的文字不再是文字,而是相应的字体编码,通过复制或者简单的采集是无法采集到编码后的文字内容!必须通过程序去处理才能达到采集成本。
效果展示!
0x1 思路
细心的人会问,为什么不把所有的内容都替换成编码呢?这个就涉及到加载和渲染速度的问题。还有如果启动字体反爬虫,基本上已经告别SEO了,请仔细考虑中间的厉害关系,你懂得!
我们知道,单纯汉字就有好几千个,还有各种字符,有的还包含各种外国人的字符串!如果全部放到自定义字体库中的话,这个文件灰常大,几十兆是肯定有的了,那后果啥样就很清楚了,加载肯定很慢,更糟糕的是如此之多的字体需要浏览器去渲染,那效果,卡到爆!!!
为了解决这个问题,我们可以选择只渲染少量的、部分的文字,假设50个字,那么字体库就会小到几十K了,相当于一个小图片而已,加上CDN加速之类的,解决了。具体网络上又N种方法参考方法我会贴在下面!
如此简单?50个字儿呢可不是随便随便选择的,要选择那些爬虫采集不到就会很大改变整个语句的语义的词,直接点吧,也就是量词、否定词之类的。如原文“我有一头朱佩琪,我从来都不骑”,我们把其中的“一”、“不”放到我们的自定义字库中,这样一来,爬虫采集到的就是“我有头朱佩琪,我从来都骑”,嘿嘿,如果加上数字就更叼了,“漏洞版本 .. ???“ 是不是很猥琐。
但是上述方法早已让网络各位大神破解一遍了,这可如何是好呢?办法总是有的!如果让“叼”字的编码随机变化,但字体信息不变,浏览器渲染出来还是“叼”字那不就完美了,
于是,每个网页加载的时候,都随机加载了一套字体库,字体库的内容还是50个字,但每个字的顺序编码都是变化的,虽然我们打乱了关键字的编码顺序,但是每个字对应的字体信息是不变的,例如,“是”字一共有9划,每一笔划都有相应的x、y坐标信息,浏览器正是根据这些笔划信息渲染
如果吧,unicode编码和x,y坐标都骚做改动。他需要采集我的每一套字体库并且建立关系,这样增加的爬虫的成本,美滋滋。
0x3 实现
基于微软雅黑字库信息,抽取其中的关键字的字体信息,生成ttf 后 使用下方代码 开始随机然后随机生成上千套字库,后文章显示时随机从文件或者裤中查询出一套字库,并把文章中的关键字替换成Unicode编码进行渲染!
# encoding: utf-8 # -*-*- # By:连长 『zh (www.lianzhang.org)』 # -*-*- import random from fontTools import ttx from fontTools.ttLib import TTFont def random_unicode(lengths): # 随机生成Unicode字符集 while True: shuma = ((str(random.sample(random_list, int(lengths))).replace('\'', '')).replace(',', '')). \ replace(' ', '').replace('[', '').replace(']', '') if shuma[0].isalpha(): return shuma else: continue def TTFontsXML(filenames): # 转换成XMl 到临时目录 filenametemp = "temp/toolstemp.xml" font = TTFont(filenames) font.saveXML(filenametemp) return filenametemp def TTFonts(filenames): # 转换XML转换ttf try: print("开始转换字体!!!" + filenames) ttx.main([filenames]) print ("-----------------------------------") except Exception as e: print ("Something went wrong converting ttx -> ttf/otf:") print (e) exit() def Editfile(fontsjson, files): random_list = ["a", "v", "x", "s", "q", "w", "e", "r", "t", "y", "u", "i", "o", "z", "x", "c", "v", "b", "n", "m", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ] shuma = ((str(random.sample(random_list, int(25))).replace('\'', '')).replace(',', '')). \ replace(' ', '').replace('[', '').replace(']', '') filenametemp = "temp/" + shuma + ".xml" try: with open(files, 'r+') as fileOpen: data = fileOpen.read() fileOpen.close() for key in fontsjson.keys(): data = data.replace(str(relationdic[key]), str(fontsjson[key])) data = data.replace(str(relationdic[key]).upper(), str(fontsjson[key]).upper()) with open(filenametemp, 'w') as f: f.write(data) f.close() return shuma + ".ttf", filenametemp except Exception, ex: print ex filenametemp = "error" filenames = "" return filenametemp, filenames if __name__ == '__main__': random_list = ['e', 'a', 'd', 'f', 'c', 'b', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] ttf_patn = "FontTest.ttf" # 请输入ttf文件绝对路径: unicodelengths = 4 # 输入 UniCode 长度: ttfnumber = 10 # 输入生成多少个文件: relationdic = {"0": "e2f1", "1": "efab", "2": "eba3", "3": "eba5", "4": "edfd", "5": "c57f", "6": "e261", "7": "f4d2", "8": "bad5", "9": "d4c2", "A": "bfec5", "B": "fc736", "C": "e6d21", "D": "be4a9", "E": "c0e8f", "F": "d3c26", "G": "b18a0", "H": "acb06", "I": "fd33e", "J": "fd36e", "K": "d417c", "L": "ad31e", "M": "ec95a", "N": "b39ce", "O": "d508a", "P": "a961d", "Q": "a76b0", "R": "b7f12", "S": "b0426", "T": "d5941", "U": "ede47", "V": "fc5a6", "W": "ed947", "X": "fd781", "Y": "b761a", "Z": "af370", "a": "fde89", "b": "ecb21", "c": "c123c", "d": "b4c2c", "e": "cbbc7", "f": "c10cb", "g": "cb78b", "h": "fdac7", "i": "076fe", "j": "d0def", "k": "ed6de", "l": "eaa1a", "m": "de1e9", "n": "9eaa5", "o": "123e5", "p": "e12e2", "q": "e5efd", "r": "e6ea9", "s": "e1e8a", "t": "b8eac", "u": "23e1c", "v": "ea6ac", "w": "b87de", "x": "e5dac", "y": "2ccea", "z": "3ada9"} # 必须当前混淆ttf填入关系 否则不知道谁是谁了。。。生成的json 文件也是错误的。。 try: macs = len(relationdic) + 50 * ttfnumber # 可能会有重复 多加点 tem_list = [] for x in range(0, int(macs)): tem_list.append(random_unicode(unicodelengths)) tem_list = list(set(tem_list)) # 去重 tempfontsxmlpa = TTFontsXML(ttf_patn) # 转换到临时XML地址。。 okjson = [] for f in range(0, ttfnumber): relationdictemp = relationdic.copy() for key in relationdictemp.keys(): b = random.sample(tem_list, 1) tem_list.remove(b[0]) relationdictemp[key] = b[0] filenames, filenametemp = Editfile(relationdictemp, tempfontsxmlpa) if filenametemp != "error": # 如果返回修改成功 启动转换ttf的程序! TTFonts(filenametemp) jsonSeve = {"url": filenames, "data": relationdictemp} okjson.append(jsonSeve) except Exception, ex: print ex
Git: https://github.com/hackxx/AntiCrawlerFontGeneration
上述代码中 不带x,y混淆,请自己修改代码谢谢,如有需要请联系我!
0x4 参考
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 反爬虫之字体反爬虫
- Python爬虫 - 记一次字体反爬
- Python爬虫实例:爬取猫眼电影——破解字体反爬
- CSS 字体:字体特性
- iOS 自定义字体设置与系统自带的字体
- ReactNative字体大小不随系统字体大小变化而变化
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
深入理解TensorFlow:架构设计与实现原理
彭靖田、林健、白小龙 / 人民邮电出版社 / 2018-5-1 / 79.00元
本书以TensorFlow 1.2为基础,从基本概念、内部实现和实践等方面深入剖析了TensorFlow。书中首先介绍了TensorFlow设计目标、基本架构、环境准备和基础概念,接着重点介绍了以数据流图为核心的机器学习编程框架的设计原则与核心实现,紧接着还将TensorFlow与深度学习相结合,从理论基础和程序实现这两个方面系统介绍了CNN、GAN和RNN等经典模型,然后深入剖析了TensorF......一起来看看 《深入理解TensorFlow:架构设计与实现原理》 这本书的介绍吧!