58同城数字字体反爬

1.什么是字体反爬

字体反爬也就是自定义字体反爬,通过调用自定义的ttf文件来渲染网页中的文字,而网页中的文字不再是文字,而是相应的字体编码,通过复制或者简单的采集是无法采集到编码后的文字内容
比如58我们在网页源代码中就看不见 数字
在这里插入图片描述
在这里插入图片描述

2.字体反爬解决方法

2.1目标
***1.一般情况下为了考虑网页渲染性能,通常网页开发者会把字体编码成base64的方式,因此我们可以到网页中找到@font-face属性,然后获取里面的base64代码,再用Python代码进行解码,然后再保存本地。
这就是58的font——face在这里插入图片描述
***2.如果没有使用base64,还有另外一种方式,就是直接把字体文件放到服务器上,然后前端通过@font-face中的url函数进行加载。 这种把文件下载下来就行

2.2 分析
***1.分析字体需要将字体转换成xml文件,然后查看其中的cmap和glyf中的属性。其中cmap存储的是code和name的映射,而glyf下存储的是每个name下的字体绘制规则。
打开文件 保存在本地的文件(运行代码后会有) 通过这里我们就可以找到 code 与 name 的关系 即

	0: glyf['glyph00001'],
    1: glyf['glyph00002'],
    2: glyf['glyph00003'],
    3: glyf['glyph00004'],
    4: glyf['glyph00005'],
    5: glyf['glyph00006'],
    6: glyf['glyph00007'],
    7: glyf['glyph00008'],
    8: glyf['glyph00009'],
    9: glyf['glyph00010']

而下面就可以找到 name 和 对应的书写规则的关系
在这里插入图片描述

***2.从第1步中我们知道了name对应的字体的绘制规则,但是还是不知道字体是长什么样子,那么可以通过一款叫做FontCreator的软件来打开.tff的字体文件,这样就可以看到每个name对应的字体最终的呈现效果。 比如 58就是这样的

2.3 映射关系
***1.在网页中,直接显示的是字体的code,而不是name。并且网页开发者为了增加爬虫的难度,有可能在多次请求之间code->name->最终字体的映射会发生改变。但是最终字体的形状是不会改变的,因此我们可以通过形状对比来进行判断。
***2.我们可以通过分析字体,得出每个字体形状对应的文字,然后保存到一个字典中。以后再请求网页的时候,就进行反向解析,先获取字体的形状,再通过字体形状反向获取代号所对应的具体文字内容。
对于映射关系下面是我自己的理解:
这个映射关系 就相当于 比如 a ——>1——>对应1的写法 b ——> 2——>对应2的写法
反爬中 a,b 会不断 变化 但是 啊 对应的 1 和 2 的 和其写法 不会变噻 就可以先找到1(2)——>1(2)的写法的关系

就相当于上面的code–name—name的写法规则 而其中code可以随时变 但name—name的写法规则不会变 我们就是从这不变的找到突破点的
也可以看一看这里关于映射

源码

import requests
import re
import base64
from fontTools.ttLib import TTFont
import io
  #1.先得到  文字形状 与  数字 映射关系
font_face = "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"
b = base64.b64decode(font_face)     #这是二进制
with open("z 58字体测试.ttf",'wb') as fp:
    fp.write(b)                          #第一次需要保存下来   写入文件进行分析
baseFont = TTFont("z 58字体测试.ttf")       #传入TTFont中
baseFont.saveXML("z 58字体测试.ttf")      #必须将 ttf 转为 xml  格式  才能进行   文本操作
glyf=baseFont['glyf']      #获取glyf   如果要获取glyf下文字形状绘画规则 可以 glyfs=baseFont['glyf']['glyph00001'](加name)
baseFontmap={
    0: glyf['glyph00001'],
    1: glyf['glyph00002'],
    2: glyf['glyph00003'],
    3: glyf['glyph00004'],
    4: glyf['glyph00005'],
    5: glyf['glyph00006'],
    6: glyf['glyph00007'],
    7: glyf['glyph00008'],
    8: glyf['glyph00009'],
    9: glyf['glyph00010'],
}          #这里就是映射关系
   #2.从网上抓取网页源代码   获取code 然后 在通过code 得到name  最后通过name得到  文字形状 再得到数字
headers={
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
}
url='https://cq.58.com/pinpaigongyu/?PGTID=0d200001-0002-5352-89f9-d8207ab2baf8&ClickID=4'
resp=requests.get(url,headers=headers)
txt=resp.text
pat="'data:application/font-ttf;charset=utf-8;base64,(.*?)'"
text=re.compile(pat).findall(txt)[0]
font_byte=io.BytesIO(base64.b64decode(text))   #将解码后的放入内存中 速度比现存在本地后读取快很多  (网页源代码中code 因为会变 又是时需要重新获取)
currentfont=TTFont(font_byte)
#code -->name
codeNameMap=currentfont.getBestCmap()      #返回xml文件中camp中的东西(含有code与name的关系)  得到的是字典
currentGlyf = currentfont['glyf']
for code,name in codeNameMap.items():
    #print({'code':hex(code),'name':name})     #items()方法把字典中每对key和value组成一个元组,并把这些元组放在列表中返回
    currentshape=currentGlyf[name]             #通过 name  得到 文字形状 绘画规则
    for number,shape in baseFontmap.items():   #在第一次得到的映射中 经行文字形状 对比
        if currentshape==shape:
            code = str(hex(code)).replace('0','&#',1) + ';'    # 得到的code 变为网页源代码上的code
                                                               # 1 代表只替换 一个 0 且顺序从前面开始
            #print({'code':code,'number':number})
            txt = re.sub(code, str(number), txt)         #对比上 就用number来换code进行替换
print(txt)
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值