环境:Windows7 +Python3.6+Pycharm2017
目标:猫眼电影票房

前言:字体反爬,也是一种常见的反爬技术,例如猫眼电影票房,汽车之家,天眼查等网站。这些网站采用了自定义的字体文件,在浏览器上正常显示,但是爬虫抓取下来的数据要么就是乱码,要么就是变成其他字符。采用自定义字体文件是CSS3的新特性,详情参考 CSS3字体
一、猫眼电影

打开猫眼电影票房 https://piaofang.maoyan.com/?ver=normal ,打开浏览器开发者模式,可以看到这些票房数据在HTML代码中是显示不了的。

点击上图右上角的Sources,把这个html文档下载下来,在编辑器打开,就可以看到这些方框对应的是一个个编码,这些编码是自定义的,所以用utf-8编码方式是显示不出来的。浏览器显示的时候因为采用了自定义的字体文件,所以显示正常。


我们来找一下这个字体文件 ,在html页面中搜索关键字:font-face,找到如下内容。一大串字符串,从base64后面开始一直到后面format前面的括号中的内容,应该是字体文件的内容。是经过了base64编码后的形式。把这一段字符串考出来,用base64解码后再保存成本地ttf文件(ttf是字体的一种类型)。

处理代码如下,先解码,再保存成本地文件 zt02.ttf:

import base64font_face='d09GRgABAAAAAAgoAAsAAAAAC7gAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADMAAABCsP6z7U9TLzIAAAE8AAAARAAAAFZW7le/Y21hcAAAAYAAAAC/AAACTCb1coxnbHlmAAACQAAAA5YAAAQ0l9+jTWhlYWQAAAXYAAAALwAAADYS0muuaGhlYQAABggAAAAcAAAAJAeKAzlobXR4AAAGJAAAABIAAAAwGhwAAGxvY2EAAAY4AAAAGgAAABoGpAXQbWF4cAAABlQAAAAfAAAAIAEZADxuYW1lAAAGdAAAAVcAAAKFkAhoC3Bvc3QAAAfMAAAAWwAAAI/dSbWYeJxjYGRgYOBikGPQYWB0cfMJYeBgYGGAAJAMY05meiJQDMoDyrGAaQ4gZoOIAgCKIwNPAHicY2Bk0mWcwMDKwMHUyXSGgYGhH0IzvmYwYuRgYGBiYGVmwAoC0lxTGBwYKn54MOv812GIYdZhuAIUZgTJAQDcwAtSeJzFkj0Kg0AQhd+qSYymSBnwCgEr76Ctvaew8QQ5QW5gY50qxxF/EGwFsTNvHZuAtsks38K8XWaGmQFwAGCSO7EA9YaCthdVtegmnEW38KB/w5WKjayMq6IOGr/1urxPhnSMpnCe+WP/ZcsUI24d/eIw0xEn1ugyu40zDMrHnUg/MPW/1N92We7n6rkkW2GJZSzouVWFoGdcBwJ7isYX2F20nqB3ocsFHbNPBL0XQypwChgjgfPAFAowPt8GPegAeJxFk89v2mYcxt/XVHZKKCHDPwppAWOCDSTB8S8COIZCoM1PRgKEkJaGqKU0W9ssarq0jbaWbpPaaX9Ad5m0wy7VDr130rSetk5bDvsDJu262yr1EsFeA9l8sPS1Zb/P83meL4AAdP8GEiABBkBMpkgPKQB0oan7FgPY74ADUfTGA2XJgDEDzkKFxwmc8wdVRZMlD6RIO+T8fJCHSpDz4xTJ0JL25bAuhpO8HSegKzoR23jw6fbcvp68VygrmhW2VmeSlVD4fuF7XR03VLc2NnQKD7vdj3Zufb74VfvZt+WpaBkmlzbqK/lQZN3UA3u3d0hPAIBxilVihgWpiWm9QwnegBJNkThhh4TdQsB3HX7YOibEg4kCFVrUU0uwdvrgtwM2QmZFQWLeGyqVvB5XNKr6xIXzM9fnF/LW5s298uSyxKQEdvIscwYdZ/mPAQm8YBIAp+nZPIcwbePINJpjJC1Lpg4/biFpBg1af3r54e6rvZ1Mrv3HhXRezCgix2abF875x/0hn0yFSp8U4WfCzvs37yy1BPpq5sqhoTfy9e+UlM9bz6Y7T/kc6aRI/tFqsZ8H8n+M/QqsAGljVVaF8qhMcRQ/aoHZzi8wf6nRqP75ogiPOmLxxTF69kOfW/cf2EUeIoMUNYVHyIgYI2nqAB4SLEuMByJ+PWMoXL49clEzynxIdwes9vhGSpPnrFVHPFFKSNOqNJ26+LR19fD0z4uZyiEvWJdhclZMGZmRWnTafba6tUiPXM5febJb+z+7faTBhpRzoygjVTPDk+F+1dcS5mfGhOE4Jnp0R9kvuUTmpH+wg77xgQn0dbAn2syXMpAJut86xL8nnWYg2fOmmuDh1zYqoIR9YcZ2xrcprx8mrmVuP1vKflTWVFvnOZ8LasXCvRJGK8w4442fX9Omp9rN7N3Zb14d1VfFqVLnzUQ5UlueX68MtHex18CJ8ldZCrULJzizeaaDKDzisnOy0zW0CUcd3qQnzWK3y7lA4/7DdO2DcFM/uBO/HBzk8BY7hf2EmnSSQx++k6VYYuDJ3Cu0SV9Y57V0tZKNZMm1HLzW+Yv3zXH1x/Hcx9uzxtDrXGb7eSXotcLd0o808/jG1qV1baZ2wux40FfgRDsCe3AGm2H+G7VV0hx8ELEMu9ytlb3kOYfDZh+7Xrih52vFB2th4WFgEjbaCyulzXBav5Vq8itrC9U3L+/uw61kQs6AfwHWE+DCAAB4nGNgZGBgAOLaDQuN4/ltvjJwszCAwPWbk38j6P9vWBiYzgO5HAxMIFEAYxgM+AB4nGNgZGBg1vmvwxDDwgACQJKRARXwAAAzYgHNeJxjYQCCFAYGJh3iMAA3jAI1AAAAAAAAAAwAVACOANQA8AEyAUwBkAG0AeYCGgAAeJxjYGRgYOBhMGBgZgABJiDmAkIGhv9gPgMADoMBVgB4nGWRu27CQBRExzzyAClCiZQmirRN0hDMQ6lQOiQoI1HQG7MGI7+0XpBIlw/Id+UT0qXLJ6TPYK4bxyvvnjszd30lA7jGNxycnnu+J3ZwwerENZzjQbhO/Um4QX4WbqKNF+Ez6jPhFrp4FW7jBm+8wWlcshrjQ9hBB5/CNVzhS7hO/Ue4Qf4VbuLWaQqfoePcCbewcLrCbTw67y2lJkZ7Vq/U8qCCNLE93zMm1IZO6KfJUZrr9S7yTFmW50KbPEwTNXQHpTTTiTblbfl+PbI2UIFJYzWlq6MoVZlJt9q37sbabNzvB6K7fhpzPMU1gYGGB8t9xXqJA/cAKRJqPfj0DFdI30hPSPXol6k5vTV2iIps1a3Wi+KmnPqxVhjCxeBfasZUUiSrs+XY82sjqpbp46yGPTFpKr2ak0RkhazwtlR86i42RVfGn93nCip5t5gh/gPYnXLBAHicbco7DoAgEIThHXyj3kVZECwxyl1s7Ew8vnFp/ZsvmQwpymn6b4BCgRIVajRo0UGjx4CR8DT3daZgw+dhYja6XXTzJjI70Zokf/YsLnaVfXJG9JGJXhiiF2UA'b=base64.b64decode(font_face)
with open('zt02.ttf','wb')as f:f.write(b)

接下来我们要查看和处理这个字体文件,这里要用到两个工具。一个是软件 FontCreator,可以直接打开ttf字体文件,查看每一个字符对应的编码。还有一个是python第三方库fontTools,借助这个库可以用python代码来操作ttf文件。

FontCreator安装:

安装包下载地址 :链接:https://pan.baidu.com/s/1zKIr7EcGlMSSF6e9Z6IZmw 提取码:d4gm (如果无效的话自己百度下)

安装好后,不用激活也能免费试用30天,Use Evaluation Version 。然后点击左上角打开文件,打开我们上面保存的zt02.ttf文件。

打开后看到如下界面,可以看到数字2 9 6上面的编码和我们之前html中看到的编码是一致的。


思路分析

这里补充一点就是你每次访问加载的字体文件中的字符的编码可能是变化的,就是说网站有多套的字体文件。

既然编码是不固定的,那就不能用编码的一一对应关系来处理字体反爬。这里要用到上面说的三方库fontTools,利用fontTools可以获取每一个字符对象,这个对象你可以简单的理解为保存着这个字符的形状信息。而且编码可以作为这个对象的id,具有一一对应的关系。像猫眼电影,虽然字符的编码是变化的,但是字符的形状是不变的,也就是说这个对象是不变的。

基本思路:先下载一个字体文件保存到本地(比如叫01.ttf),人工的找出每一个数字对应的编码。当我们重新访问网页时,同样也可以把新的字体文件下载下来保存到本地ttf(比如叫02.ttf)。网页中的一个数字的编码比如为AAAA,如何确定AAAA对应的数字。我们先通过编码AAAA找到这个字符在02.ttf中的对象,并且把它和01.ttf中的对象逐个对比,直到找到相同的对象,然后获取这个对象在01.ttf中的编码,再通过编码确认是哪个数字。

具体实现:

先安装 fontTools,应该是直接 pip install fonttools 就可以

基本命令介绍:

from fontTools.ttLib import TTFontfont=TTFont('01.ttf')    #打开本地字体文件01.ttf
font.saveXML('01.xml')   #将ttf文件转化成xml格式并保存到本地,主要是方便我们查看内部数据结构

先把字体文件转化成xml格式,以便打开查看里面的数据结构。打开xml文件可以看到类似html标签的结构。这里我们用到的标签是<GlyphOrder…>和<glyf…> 。

点开标签内部,<GlyphOrder…>内包含着所有编码信息,注意前两个是不是0-9的编码,需要去除。

<glyf…> 内包含着每一个字符对象,同样第一个和最后一个不是0-9的字符,需要祛除。

点开对象,里面的信息如下,是一些坐标点的信息,可以联想到这些点应该是描绘字体形状的,后面再讲。

实现步骤:先在本地保存字体文件01.ttf,并手动确认编码和数字的对应关系,保存到字典中。然后重新访问网页的时候,把网页中新的字体文件也下载保存到本地02.ttf。对于02中的编码uni2,先获取uni2的对象obj2,与01中的每一个对象注逐一对比,直到找到相同的对象obj1,再根据obj1的编码,在字典中找到对应的数字。

获取猫眼数据完整代码:

import requests
from fontTools.ttLib import TTFont
from lxml import etree
import  lxml.html as H
import base64
import re
#破解猫眼数据字体加密
url='https://piaofang.maoyan.com/?ver=normal'headers={"User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"}#获取猫眼字体库
def ziti_ku():response=requests.get(url,headers=headers)session = requests.session()con = session.get(url, headers=headers)doc = H.document_fromstring(con.content)#用正则匹配获取字体代码(记得改变格式.decode('utf-8'))font_data_origin = re.search(r'base64,(.*?)\)', con.content.decode('utf-8'), re.S).group(1)font_data_after_decode = base64.b64decode(font_data_origin)#创建字体文件new_font_name = "maoyan1.ttf"with open(new_font_name, 'wb') as f:f.write(font_data_after_decode)#新旧字体对照表,方便破解字体加密使用
def duizhao_biao():font1 = TTFont('zt02.ttf')  # 打开本地字体文件zt02.ttfobj_list1 = font1.getGlyphNames()[1:-1]  ##获取所有字符的对象,去除第一个和最后一个uni_list1 = font1.getGlyphOrder()[2:]  # 获取所有编码,去除前两个# 手动确认编码和数字之间的对应关系,保存到字典中dict = {'uniE624': '4', 'uniE219': '7', 'uniEE6C': '2', 'uniE5F8': '8', 'uniEA0C': '5', 'uniE32A': '3','uniE0F1': '9', 'uniE1CC': '6', 'uniF24D': '0', 'uniF842': '1'}font2 = TTFont('maoyan1.ttf')  # 打开访问网页新获取的文字字体maoyan.ttfobj_list2 = font2.getGlyphNames()[1:-1]uni_list2 = font2.getGlyphOrder()[2:]for uni2 in uni_list2:obj2 = font2['glyf'][uni2]  # 获取编码uni2在02.ttf中对用的对象for uni1 in uni_list1:obj1 = font1['glyf'][uni1]if obj1 == obj2:print(uni2, dict[uni1])  # 打印结果,编码uni2和对应的数字
#字体加密破解
def zhiti_transfrom():##=================分析出新旧字体库对应码======================================================font1 = TTFont('zt02.ttf')  # 打开本地字体文件zt02.ttfobj_list1 = font1.getGlyphNames()[1:-1]  ##获取所有字符的对象,去除第一个和最后一个uni_list1 = font1.getGlyphOrder()[2:]  # 获取所有编码,去除前两个# 手动确认编码和数字之间的对应关系,保存到字典中dict = {'uniE624': '4', 'uniE219': '7', 'uniEE6C': '2', 'uniE5F8': '8', 'uniEA0C': '5', 'uniE32A': '3','uniE0F1': '9', 'uniE1CC': '6', 'uniF24D': '0', 'uniF842': '1'}font2 = TTFont('maoyan1.ttf')  # 打开访问网页新获取的文字字体maoyan.ttfobj_list2 = font2.getGlyphNames()[1:-1]uni_list2 = font2.getGlyphOrder()[2:]for uni2 in uni_list2:obj2 = font2['glyf'][uni2]  # 获取编码uni2在02.ttf中对用的对象for uni1 in uni_list1:obj1 = font1['glyf'][uni1]if obj1 == obj2:print(uni2, dict[uni1])  # 打印结果,编码uni2和对应的数字##================================对新的网页的数据进行字体解码======================================================response=requests.get(url,headers=headers)response.encoding=('utf-8')html=response.texthtml=etree.HTML(html)content=html.xpath('//*[@id="ticket_tbody"]/ul')for i in content:film_name=i.xpath('li[1]/b/text()')[0]            #电影名称#==========================实时票房===========================real_piaofang=i.xpath('li[2]/b/i/text()')     #实时票房real_piaofang=str(real_piaofang).replace('.','').replace("['",'').replace("']",'').replace('\\',',').strip(',').split(',')t=len(real_piaofang)a=[]for t1 in range(t):pf='uni'+real_piaofang[t1].replace('u','').upper()obj2 = font2['glyf'][pf]  # 获取编码uni2在02.ttf中对用的对象for uni1 in uni_list1:obj1 = font1['glyf'][uni1]if obj1 == obj2:d=dict[uni1]# print(pf, dict[uni1])  # 打印结果,编码uni2和对应的数字a.append(d)real_piaofang=''.join(a)real_piaofang=real_piaofang[:-2] +'.'+real_piaofang[-2:]#===============================#票房占比============================================piaofang_zb=i.xpath('li[3]/i/text()')piaofang_zb = str(piaofang_zb).replace('.', '').replace("['", '').replace("']", '').replace('%','').replace('\\',',').strip( ',').split(',')t = len(piaofang_zb)a = []for t1 in range(t):pf = 'uni' + piaofang_zb[t1].replace('u', '').upper()obj2 = font2['glyf'][pf]  # 获取编码uni2在02.ttf中对用的对象for uni1 in uni_list1:obj1 = font1['glyf'][uni1]if obj1 == obj2:d = dict[uni1]# print(pf, dict[uni1])  # 打印结果,编码uni2和对应的数字a.append(d)piaofang_zb = ''.join(a)piaofang_zb = piaofang_zb[:-1] + '.' + piaofang_zb[-1:] +'%'#=============================#排片占比======================================================paipian_zb=i.xpath('li[4]/i/text()')       #排片占比paipian_zb = str(paipian_zb).replace('.', '').replace("['", '').replace("']", '').replace('%','').replace('\\', ',').strip( ',').split(',')t = len(paipian_zb)a = []for t1 in range(t):pf = 'uni' + paipian_zb[t1].replace('u', '').upper()obj2 = font2['glyf'][pf]  # 获取编码uni2在02.ttf中对用的对象for uni1 in uni_list1:obj1 = font1['glyf'][uni1]if obj1 == obj2:d = dict[uni1]# print(pf, dict[uni1])  # 打印结果,编码uni2和对应的数字a.append(d)paipian_zb = ''.join(a)paipian_zb = paipian_zb[:-1] + '.' + paipian_zb[-1:]+'%'#==============================上座率====================================================shangzl=i.xpath('li[5]/span[1]/i/text()')  #上座率shangzl = str(shangzl).replace('.', '').replace("['", '').replace("']", '').replace('%', '').replace('\\',',').strip(',').split(',')t = len(shangzl)a = []for t1 in range(t):pf = 'uni' + shangzl[t1].replace('u', '').upper()obj2 = font2['glyf'][pf]  # 获取编码uni2在02.ttf中对用的对象for uni1 in uni_list1:obj1 = font1['glyf'][uni1]if obj1 == obj2:d = dict[uni1]# print(pf, dict[uni1])  # 打印结果,编码uni2和对应的数字a.append(d)shangzl = ''.join(a)shangzl = shangzl[:-1] + '.' + shangzl[-1:] + '%'print(film_name,real_piaofang,piaofang_zb,paipian_zb,shangzl)if __name__=='__main__':ziti_ku()# duizhao_biao()zhiti_transfrom()

作者:Mars_DD
来源:CSDN
原文:https://blog.csdn.net/xing851483876/article/details/82928607

字体反爬虫处理猫眼(数字)相关推荐

  1. Python 爬虫工程师必看,深入解读字体反爬虫

    字体反爬虫开篇概述 很多人学习python,不知道从何学起. 很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手. 很多已经做案例的人,却不知道如何去学习更加高深的知识. 那么针对这 ...

  2. 深入细枝末节,Python的字体反爬虫到底怎么一回事

    内容选自 即将出版 的<Python3 反爬虫原理与绕过实战>,本次公开书稿范围为第 6 章--文本混淆反爬虫.本篇为第 6 章中的第 4 小节,其余小节将 逐步放送 . 字体反爬虫开篇概 ...

  3. 用前考虑清楚,伤敌一千自损八百的字体反爬虫

    内容选自即将出版的<Python3 反爬虫原理与绕过实战>,本次公开书稿范围为第 6 章--文本混淆反爬虫.本篇为第 6 章中的第 4 小节,其余小节将逐步放送. 字体反爬虫开篇概述 在 ...

  4. 【python实现网络爬虫(4)】实习僧网站信息爬取(字体反爬虫破解)

    实习僧网站 实习僧网址,地址为北京,在搜索框输入"python",如下 实战解析 步骤一.建立for循环爬取前20页的内容 首先.查看翻页URL的信息,找规律 第一页:https: ...

  5. 快手字体反爬虫?请给我10分钟,让我破了他

    文章目录 前景摘要 字体反爬虫 突破字体反爬虫思路的探索 最终突破快手反爬虫代码 前景摘要 最近一个朋友问我,字体反爬虫的事,他发给我一个快手网站,我由于比较忙没回他,于是后来他说解决不了就要上scr ...

  6. 字体反爬之猫眼票房爬虫python

    编译环境:win10+python3.6+pycharm2017 目标:获取猫眼票房的电影名称和票房数据 目标网址:https://piaofang.maoyan.com/?ver=normal 网址 ...

  7. python爬虫之字体反爬虫

    原因 今天下午在抓取一个网页时,发现的网页字体反爬,这种情况一句话总结:即网页文本里的数字与网页上显示的字体不一致.为什么会出现这样的情况呢?原因是开发者在网页文本里引入了改变字体的文件. 然后可以看 ...

  8. pythonttf字体反爬虫_利用Python采集起点中文网小说,并解决字体反爬的问题

    个人比较喜欢看小说,于是乎想利用Python爬取小说网站--起点中文网,在Python编程爬取定位过程中遇到了Python反爬虫,咨询了我旁边的前端大神,说下方法 当前页面接口返回的html源码 当前 ...

  9. pythonttf字体反爬虫_Python爬虫---汽车之家字体反爬

    本篇文章给大家带来的内容是关于Python爬虫---汽车之家字体反爬,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 目标网站:汽车之家 目标网址:https://club.autoh ...

最新文章

  1. mysql之基础操作grant、show、repair、log_error等
  2. 人脸识别百亿蓝海之下,还需解决两方面问题
  3. Windows安装MongoDB可视化工具adminMongo
  4. 怎么添加新项目到svn服务器,用eclipse+svn插件,上传新项目到svn服务器
  5. JDK1.5-1.7 比较二
  6. google nexus5x 刷机抓包逆向环境配置(三)
  7. Windows系统MySQL安装配置
  8. 工频干扰频谱测量_【鼎阳硬件智库译文|高速总线之测试测量】定量测量多通道串行数据系统中的串扰引起的抖动...
  9. Mysql日期和时间函数大全
  10. STM32 ADC 单次模式、连续模式、扫描模式(转载)
  11. docx文档怎么排列图片_“胶水语言”办公自动化Word篇——使用Python编辑和读取Word文档
  12. 2010中国存储创新年会
  13. idea 离线安装 idea json view 插件
  14. 精品|从零开始-基于FPGA 的软核处理器设计实现
  15. java 中文文件路径乱码 解决方法
  16. Java设计模式--生成器模式
  17. 对话系统 | (4) 任务型对话系统基础
  18. 为什么要写技术博客?
  19. 设计物联网系统的步骤和原则有哪些
  20. iOS AppStore 转让APP

热门文章

  1. c语言oj数据通过,OJ输入数据的处理
  2. 实现FTP服务器免登陆下载PDF文件转base64在下载到本地|服务器
  3. 参数调优:K折交叉验证与GridSearch网格搜索
  4. 如何生成token,是使用token
  5. 用Matlab解决数学问题
  6. vue2.x的h函数(createElement)与vue3中的h函数
  7. 程序员可选择的个博客论坛网站
  8. 网页中插入FLASH(swf文件)的html代码
  9. 神州数码无线设备常用配置
  10. dyld: Library not loaded: /usr/local/opt/openssl/lib/libssl.1.0.0.dylib