添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
  • python字体反爬的一种解决方案
    • 版权声明
    • 问题
    • 描述
    • 解决方案
    • 实操过程
    • 请注意: 本文章为原创文章,未经本人许可,任何人不得转载和借鉴

      目前越来越多的网站升级了应对爬虫的反制手段和措施,网站使用 自定义字体 或者人们常说的 字体反爬 ,就是其中一种。

      这里我们以某网站为例
      打开某网站的某一篇政策文章,点击右键、打开 检查 ,或者 F12

      可以发现,【申报条件】这个板块里面的文字,和源代码里的文字完全不一样;
      比如“ 申请企业应具备以下条件: ”,代码里则对应为:“ 者合册第应具步以督法快: ”;
      即使你选中文字,再把它们复制出来,文字粘贴后依然为:“者合册第应具步以督法快:”。

      解决该问题的一种基本思路是: 构建源字体与替换字体的对应关系
      比如上文提到的句子:
      者合册第应具步以督法快 替换为 申请企业应具备以下条件
      其中: > | > | >
      假如我们能有这样的一个对应字典

      change_font = {'者': '申', '合': '请', '册': '企', ... , }
      

      那么我们就能够将网站爬到的所有字体,都替换成正确的文字。

      1、找到网站的字体文件(ccw.ttf)

      F12打开检查后,点击Network,刷新我们刚才访问的政策链接,在众多链接中,找到网站的字体文件链接
      在这里插入图片描述
      然后在浏览器中打开该链接,并保存到本地

      2、使用百度字体编辑器

      接下来,我们需要用到百度的在线字体编辑器,网址为:http://fontstore.baidu.com/static/editor/index.html
      打开该网站后,点击左上角的打开,然后上传刚才保存的字体文件
      在这里插入图片描述
      打开后:
      在这里插入图片描述
      这时候我们就能看到网站字体和编码对应的关系
      在这里插入图片描述

      3、fontTools库

      接下来我们使用python解析字体的常用库:fontTools

      >>>from fontTools.ttLib import TTFont
      >>>FONT_FILE = r'C:\Users\17337\Downloads\ccw.ttf'
      >>>font_file = TTFont(FONT_FILE)
      >>>for k, v in font_file['cmap'].getBestCmap().items():
      >>>    print(k, v)
      33 ampersand
      35 greater
      37 asciitilde
      ...
      ...
      39069 uni989D
      39318 uni9996
      39564 uni9A8C
      39640 uni9AD8
      40857 uni9F99
      

      这里getBestCmap返回的是一个unicode cmap字典,即编码和图形的对应关系。

      请注意:这里key为字体的编码,value为每个字体对应的独特的id值,这里为了方便理解,我们可以把这个value理解成字体的注释

      结合步骤2展示的字体,我们可以随便找一个字体作为切入点,比如刚才打印的最后一对键值对

      40857 uni9F99
      

      编码为:40857 ,注释为:uni9F99
      在我们刚才打开的百度字体编辑器的第三页,有一个字体【八】正好也是uni9F99
      在这里插入图片描述
      除了注释uni9F99对上了,还有其他我们能着手的点吗?
      仔细看【八】这个【$9F99】,和我们的编码【40857】
      一个看起来像是16进制,一个看起来像是十进制,这两个数字有关联吗

      >>>hex(40857)  # 十进制转十六进制
      '0x9f99'
      

      答案是:字体编辑器的上面这个编码【$9F99】,正是【40857】的十六进制表示。

      所以,现在我们知道了,【uni9F99】这个注释对应的字体就是【八】,也能通过fontTools找到这个对应关系,但是我们现在还不知道的是:哪个源代码的字体要替换成【八】

      回到我们刚才打开的政策网页,【申报材料】里,正好也有一个【八】

      很显然,源代码的【龙】字,实际展示时,为【八】这个汉字
      所以,源代码里:要替换成
      那么前端代码在处理和展示的时候,怎么知道要替换成,或者说替换成这个字体图形?
      显然是有一套通用的处理规则,我们现在就是要找出这套转换规则
      从【龙】这个汉字入手:
      【龙】utf8编码为【\xe9\xbe\x99】
      【龙】gbk编码为【\xc1\xfa】
      【龙】的Ascii数值为【40857】

      >>>ord('龙')
      40857
      

      40857!刚才我们使用getBestCmap返回的字典,【40857】正好对应的值是【uni9F99】,对应的字体正好是【八】!
      所以汉字【龙】> ord(‘龙’) > 40857

      现在我们只剩最后一个问题:
      如何批量构建,类似于这种【40857/$9F99/uni9F99】与【八】的对应关系?
      答案是:手动构建!
      当然,也不是完全手动构建类似 {‘uni9F99’: ‘八’, ‘six’: ‘6’, … ,} 这种字典
      有一种取巧的方式:
      fontTools库的getGlyphOrder() 方法,可以获取字体文件的所有字体注释
      该方法返回的字体注释的列表,与百度字体编辑器展示的顺序是一模一样的

      >>>font_file.getGlyphOrder()
      ['.notdef', 'nine', 'eight', 'three', 'four', 'seven', ..., 'uni9662', 'uni660E']
      

      下图为手动构建的完整的FONT_LIST(要对应百度字体编辑器)
      在这里插入图片描述
      上文所说的手动构建,就是指,把百度字体编辑器展示的字体,一个一个对应着写到一个列表里,保存起来,以后若是网站字体又有所更新,只需要修改相应的元素即可。
      所以这里我们只需要手动按顺序构建字体对应的列表FONT_LIST,即可生成对应的字典

      >>>FONT_LIST = [' ', '9', '8', '3', '4', '7', ..., '明', '局', '第']
      >>>font_dict = dict(zip(font_file.getGlyphOrder(), FONT_LIST))
      >>>font_dict
      {'.notdef': ' ',
       'nine': '9',
       'eight': '8',
       'three': '3',
       'four': '4',
       'seven': '7',
       ...
       'uni7B2C': '业',
       'uni3007': '院',
       'uni4E1A': '⚪',
       'uni5C40': '明',
       'uni9662': '局',
       'uni660E': '第'}
      

      这个font_dict有什么用呢,这还要和前文的getBestCmap方法配合起来使用

      >>>replace_dict = {}
      >>>for code, value in font_file['cmap'].getBestCmap().items():
      >>>    before_replace = chr(code)  # 源代码的汉字字符串
      >>>    after_replace = font_dict[value]  # 需要替换的汉字字体
      >>>    replace_dict[before_replace] = after_replace
      >>>replace_dict
      {'!': '&',
       '#': '>',
       '$': 'c',
       '%': '~',
       '&': 'H',
       '(': 'q',
       ...
       '革': '策',
       '项': '不',
       '须': '制',
       '额': '司',
       '首': '免',
       '验': '省',
       '高': '天',
       '龙': '八'}
      

      这个replace_dict就是我们最终的用来替换文本的字典了。
      到此,我们的实操就结束了,下面进入整体流程的代码部分。

      from fontTools.ttLib import TTFont
      FONT_FILE = r'C:\Users\17337\Downloads\ccw.ttf'
      FONT_LIST = [' ', '9', '8', '3', '4', '7', ..., '明', '局', '第']
      def get_font():
          font_file = TTFont(FONT_FILE)
          font_dict = dict(zip(font_file.getGlyphOrder(), FONT_LIST))  # 注释和真实字体的对应关系字典
          return {chr(k): font_dict[v] for k, v in font_file['cmap'].getBestCmap().items()}
      def change(text):
          replace_dict = get_font()
          return ''.join([replace_dict.get(each, each) for each in text]) if text else ''
      def test():
          chace_str = '者合册第应具步以督法快:'
          result = change(chace_str)
          print('转换前:"{}", 转换后:"{}"'.format(chace_str, result))
      if __name__ == '__main__':
          test()
      

      文章中,本人提供了一种字体反爬的解决方案,当然,也有该方案的缺陷:
      1.需要手动构建FONT_LIST列表,比较花费时间
      2.适用于某一特定网,但不一定适用于其他网站,不能作为一种普适的字体反爬的解决方案

      感谢您的观看!

      什么是字体反爬? 所谓的字体反爬就是网站一些关键字替换成自己设计的字体,这样用浏览器访问网站的时候会加载这套字体,因此在浏览器中显示是正常的字体;而在源码中这些关键字是乱码的,根本无法识别,采集下来是无用的信息 使用字体反爬的例子:抖音、大众点评、58等,如下是抖音的 解决字体反爬,以抖音为例 1 提取抖音个人主页链接 个人主页—>右上角—>分享—>复制链接,在浏览器... 爬取一些网站的信息时,偶尔会碰到这样一种情况:网页浏览显示是正常的,用python爬取下来是乱码,F12用开发者模式查看网页源代码也是乱码。这种一般是网站设置了字体反爬 这里我们以58同城为例: 点击进入https://sz.58.com/chuzu/链接: 网页显示数据为: 网页原码数据为: 从上面可以看出,生这个字变成了乱码,请大家特别注意箭头所指的数字。 在这里里我... 所以我现在要做的就是,怎么去将&#x…;字符转为对应的汉字。 先手动下载页面中的字体文件。然后使用fontTools模块,读取字体文件,并将其保存为xml格式(正常情况下,字体文件是无... 前几天在一个论坛上,看见ALT+821206(小键盘)能输入一个“囍”字,挺有意思的。实际上是,汉字编码、内码的一些东西。下面是一些常用的:猴(ALT+29492)       鸡(ALT+40481)       狗(ALT+29399) 猪(ALT+29482) 鼠(ALT+40736)       牛(ALT+29275)       虎(ALT+34382) 兔(ALT+208 前言:字体反爬,也是一种常见的反爬技术,例如58同城,猫眼电影票房,汽车之家,天眼查,实习僧等网站。这些网站采用了自定义的字体文件,在浏览器上正常显示,但是爬虫抓取下来的数据要么就是乱码,要么就是变成其他字符,是因为他们采用自定义字体文件,通过在线加载来引用样式,这是CSS3的新特性,通过 CSS3,web 设计师可以使用他们喜欢的任意字体 ,然后因为爬虫不会主动加载在线的字体字体加密一般是网页修改了默认的字符编码集,在网页上加载他们自己定义的字体文件作为字体的样式,可以正确地显示数字,但是在源码上同 页面在css中使用font-face定义了字符集,并通过unicode去映射展示,浏览器会加载css中的font字体为用户渲染好,所以浏览页面时是正常的,而对于爬虫来说却极其不友好,因为爬取下来的源代码未经过浏览器渲染,都是乱码。 1. 查找到页面中的加密字体 font_face,常见的有两种情况 1.最简单的,直接在页面源码中搜索font_face,如果能找到类似如 此篇博客为普通方式爬取安居客租房数据一共提取出1200条,但是在进行大规模的数据爬取时,不建议使用这种方式,速度太慢是最大的诟病,在进行大规模爬取时,使用分布式爬虫是第一选择 一、指定爬取数据 二、设置请求头防止反爬 三、分析页面并且与网页源码进行比对 四、分析页面整理数据 五、保存到excel表中 六、使用jupyternotebook进行简单的数据分析 一、指定爬取数据 提取价格、面积、详细标题、名称、具体位置、房屋结构、装修情况 二、设置请求头 这里设置请求头依然使用最常见的. 2. 字体反爬 2.1 字体反爬简介 ​ 在 CSS3 之前,Web 开发者必须使用用户计算机上已有的字体。目前的技术开发者可以使用@font-face为网页指定字体,开发者可将心仪的字体文件放在 Web 服务器上,并在 CSS 样式中... 可见无论是小说文字数量还是推荐数,在我们本来页面中是好好的,可在网页源码中是一对我们看不懂的字体,这其实就是字体加密,所以我想做到字体反扒,就要破解字体加密,接下来我会为大家一一概述。 2、网页爬取代码 内容过于简单,不做过多概述 import requests headers = { "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/53.. 通过这个爬虫,个人觉得代码层面是不难的,难在请求参数的解析,cookie的解析,js逆向,登录验证码解析等各种反爬虫手段,不过道高一尺,魔高一丈,总归有解决的办法!!!其次文章中,对于cookie的值我并没有进行讲解,这个根据自己实际需求进行测试,那么多的cookie不可能全都有用,大家可以通过postman对cookie的值进行删减直到获取不到数据为之!总的说请求头信息,cookie等信息并不是全部都需要传递!