实习僧网站字体反爬破解思路及步骤分享

2 篇文章 0 订阅
1 篇文章 0 订阅

需要用到的第三方包 fontTools

崔庆才博客:今天,我终于弄懂了字体反爬是个啥玩意!

哔哩哔哩视频:python零基础一节课带你玩转字体反爬

测试网站选取了实习僧:实习僧

TTF(TrueTypeFont)是Apple公司和Microsoft公司共同推出的字体文件格式,随着windows的流行,已经变成最常用的一种字体文件表示方式。

@font-face 是CSS3中的一个模块,主要是实现将自定义的Web字体嵌入到指定网页中去。

明确以ttf后缀结尾的是字体文件。前端通过自定义字体的形式来进行反爬,通常不会自定义太多字体,一般选取会明确改变句意或者爬虫需要的部分,才会进行字体反爬。

不会进行全站字体反爬的原因很简单

  1. 单单一个汉字就有极多的种类,自定义字体的文件并不小,可能几千个汉字的ttf文件就会有个几十兆的大小,那这个网站的页面请求会特慢,而且浏览器渲染的压力也会特别大
  2. 如果只对部分字体进行自定义字体,这样可以把自定义字体文件做成动态的,里面的字可以进行改变,反爬难度提升一级的同时,ttf文件的大小只有几十kb,也不会对浏览器造成很大的渲染压力

爬虫网页分析过程

  • 分析网站,发现招聘岗位信息及薪资等关键部分存在字体反爬

在这里插入图片描述

  • 进行网站源码请求,试水反爬,尝试发现源码中反爬字体对应关系
    在这里插入图片描述

  • 字体对应关系

&#xe339  生
  • 审查元素的页面,能够在右边的css中看到是用了myfont,自定义字体,在源码中搜索myfont
<style data-n-head="true" type="text/css">@font-face {    font-family: myFont;    src: url(/interns/iconfonts/file?rand=0.8190342838679106);}</style>
  • 发现src:url和根域名进行拼接,直接浏览器就自动下载一个无格式文件,将文件后缀名改为.ttf

  • 下载一个软件叫做FontCreator,然后用软件打开该文件就可以看见字体文件信息,鼠标点击一个其中一个字体就能看见信息是能够和网页源码中的信息对应起来的,或者在网页搜索百度文字然后尝试打开(测试过了,发现打不开实习僧的ttf文件,如果可以的话最好还是用软件)在这里插入图片描述

  • 经过多次测试,发现该网站的字体反爬ttf文件并不是动态的,这样就更容易了一点


    爬虫实现过程

    • 第三方工具包 fontTools

    • Python语言

  1. 首先把ttf文件请求下来,然后用fontTools.ttlib.TTFont拿到TTFont对象,再将该对象转换为xml文件
from fontTools.ttLib import TTFont
font = TTFont(r"F:\Crawl_project\Shixiseng_crawl\Shixiseng_crawl\file1.ttf")
font.saveXML(r"F:\Crawl_project\Shixiseng_crawl\Shixiseng_crawl\font.xml")

在这里插入图片描述

  1. 找到camp的位置,这里就是字体对应的信息,code位置的是十六进制的数字,name位置是值,有点类似于字典的键值对应关系
  2. 用font对象中的getBestCmap方法得到对应的字典关系
from fontTools.ttLib import TTFont
font = TTFont(r"F:\Crawl_project\Shixiseng_crawl\Shixiseng_crawl\file1.ttf")
font.saveXML(r"F:\Crawl_project\Shixiseng_crawl\Shixiseng_crawl\font.xml")
# 打印getBestCmap返回的对象类型
print(type(font['cmap'].getBestCmap()))
# 字典的key值会自动转成十进制,用字典推导式把key值转回到十六进制
cmap_dict ={hex(k):v for k,v in font['cmap'].getBestCmap().items()}
print(cmap_dict)

result:

<class 'dict'>
{'0x78': 'x', '0xe128': 'uni4EBA', '0xe150': 'uni31', '0xe1ae': 'uni4d', '0xe1c1': 'uni74', '0xe209': 'uni5468', '0xe212': 'uni52', '0xe25a': 'uni5929', '0xe278': 'uni4E2A', '0xe2e6': 'uni5E74', '0xe339': 'uni751F', '0xe361': 'uni41', '0xe37b': 'uni78', '0xe388': 'uni59', '0xe3dc': 'uni4c', '0xe4a2': 'uni47', '0xe4ef': 'uni63', '0xe4f7': 'uni35', '0xe51f': 'uni50', '0xe58f': 'uni51', '0xe607': 'uni48', '0xe659': 'uni5a', '0xe673': 'uni6d', '0xe6c0': 'uni8BBE', '0xe6e9': 'uni4f', '0xe722': 'uni5DE5', '0xe76a': 'uni94F6', '0xe820': 'uni4E00', '0xe871': 'uni37', '0xe890': 'uni53', '0xe8d5': 'uni54', '0xe8db': 'uni34', '0xe90e': 'uni6b', '0xe919': 'uni43', '0xe933': 'uni653F', '0xe9ce': 'uni8054', '0xea04': 'uni45', '0xea0f': 'uni68', '0xea47': 'uni884C', '0xea4e': 'uni8058', '0xeac0': 'uni62', '0xeb33': 'uni73', '0xeb7e': 'uni30', '0xebaa': 'uni75', '0xebb8': 'uni6708', '0xec0e': 'uni61', '0xecc3': 'uni64', '0xeccb': 'uni7A0B', '0xecd8': 'uni57', '0xecdc': 'uni4a', '0xed39': 'uni36', '0xed69': 'uni524D', '0xee5e': 'uni67', '0xef80': 'uni4E8C', '0xefa8': 'uni76', '0xefb9': 'uni7AEF', '0xf03a': 'uni4E09', '0xf069': 'uni69', '0xf0cc': 'uni4E92', '0xf0cd': 'uni8BA1', '0xf103': 'uni55', '0xf121': 'uni33', '0xf179': 'uni49', '0xf1ad': 'uni6c', '0xf1ae': 'uni38', '0xf1be': 'uni39', '0xf25e': 'uni573A', '0xf262': 'uni70', '0xf2dc': 'uni7F51', '0xf2e7': 'uni65', '0xf2ff': 'uni4b', '0xf328': 'uni42', '0xf336': 'uni46', '0xf343': 'uni6e', '0xf34e': 'uni5E7F', '0xf365': 'uni4F1A', '0xf3c6': 'uni72', '0xf3f4': 'uni56', '0xf41e': 'uni544A', '0xf43a': 'uni5E08', '0xf43f': 'uni58', '0xf4b2': 'uni4e', '0xf4b5': 'uni4EF6', '0xf4ce': 'uni56DB', '0xf4d7': 'uni7a', '0xf51d': 'uni32', '0xf524': 'uni62DB', '0xf52e': 'uni79', '0xf55c': 'uni6a', '0xf580': 'uni66', '0xf5a6': 'uni71', '0xf5eb': 'uni8D22', '0xf6b6': 'uni77', '0xf73f': 'uni5E02', '0xf7e6': 'uni8F6F', '0xf84d': 'uni4F5C', '0xf854': 'uni4E94', '0xf87d': 'uni44', '0xf8fa': 'uni6f'}
  1. 参照FontCreator的字体对应关系发现对应关系如下

    cmap的xml中:0xe339—>uni751F

    FontCreator:uni751F—>生

    所以0xe339—>uni751F—>生 这是对应关系

  2. 构建字典对应关系

    输入:

    def get_dict():
        '''
        输入:无
        输出:字体文件对应的字体字典(包含字体编码和对应字体)以及字体编码
        '''
        with open(r'F:\Crawl_project\Shixiseng_crawl\Shixiseng_crawl\font.xml') as f:
            xml=f.read()
        keys=re.findall('<map code="(0x.*?)" name="uni.*?"/>',xml)[:99]
        values=re.findall('<map code="0x.*?" name="uni(.*?)"/>',xml)[:99]
        for i in range(len(values)):
            if len(values[i])<4:
                values[i]=('\\u00'+values[i]).encode('utf-8').decode('unicode_escape')
            else:
                values[i]=('\\u'+values[i]).encode('utf-8').decode('unicode_escape')
        word_dict=dict(zip(keys, values))
        print(word_dict)
        # return word_dict,keys
        
    get_dict()
    print("-"*50)
    print(r"\u751F".encode().decode('unicode_escape'))
    

    输出:

    {'0xe128': '人', '0xe150': '1', '0xe1ae': 'M', '0xe1c1': 't', '0xe209': '周', '0xe212': 'R', '0xe25a': '天', '0xe278': '个', '0xe2e6': '年', '0xe339': '生', '0xe361': 'A', '0xe37b': 'x', '0xe388': 'Y', '0xe3dc': 'L', '0xe4a2': 'G', '0xe4ef': 'c', '0xe4f7': '5', '0xe51f': 'P', '0xe58f': 'Q', '0xe607': 'H', '0xe659': 'Z', '0xe673': 'm', '0xe6c0': '设', '0xe6e9': 'O', '0xe722': '工', '0xe76a': '银', '0xe820': '一', '0xe871': '7', '0xe890': 'S', '0xe8d5': 'T', '0xe8db': '4', '0xe90e': 'k', '0xe919': 'C', '0xe933': '政', '0xe9ce': '联', '0xea04': 'E', '0xea0f': 'h', '0xea47': '行', '0xea4e': '聘', '0xeac0': 'b', '0xeb33': 's', '0xeb7e': '0', '0xebaa': 'u', '0xebb8': '月', '0xec0e': 'a', '0xecc3': 'd', '0xeccb': '程', '0xecd8': 'W', '0xecdc': 'J', '0xed39': '6', '0xed69': '前', '0xee5e': 'g', '0xef80': '二', '0xefa8': 'v', '0xefb9': '端', '0xf03a': '三', '0xf069': 'i', '0xf0cc': '互', '0xf0cd': '计', '0xf103': 'U', '0xf121': '3', '0xf179': 'I', '0xf1ad': 'l', '0xf1ae': '8', '0xf1be': '9', '0xf25e': '场', '0xf262': 'p', '0xf2dc': '网', '0xf2e7': 'e', '0xf2ff': 'K', '0xf328': 'B', '0xf336': 'F', '0xf343': 'n', '0xf34e': '广', '0xf365': '会', '0xf3c6': 'r', '0xf3f4': 'V', '0xf41e': '告', '0xf43a': '师', '0xf43f': 'X', '0xf4b2': 'N', '0xf4b5': '件', '0xf4ce': '四', '0xf4d7': 'z', '0xf51d': '2', '0xf524': '招', '0xf52e': 'y', '0xf55c': 'j', '0xf580': 'f', '0xf5a6': 'q', '0xf5eb': '财', '0xf6b6': 'w', '0xf73f': '市', '0xf7e6': '软', '0xf84d': '作', '0xf854': '五', '0xf87d': 'D', '0xf8fa': 'o'}
    --------------------------------------------------

    6.此处就能发现很明显的对应关系了,0xe339–>生,然后请求回来源码把字典中的字符替换就行了。

  • 然后按照这个思路把代码实现就可以了,实习僧的字体文件大概一周的时间就会更换字体文件对应信息,所以代码实现时最好每次爬虫启动时抓取一次当前的字体文件
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值