56星座屋
当前位置: 首页 星座百科

python爬虫神技(Python爬虫字体反爬处理)

时间:2023-05-30 作者: 小编 阅读量: 2 栏目名: 星座百科

ver=normal,打开浏览器开发者模式,可以看到这些票房数据在HTML代码中是显示不了的。浏览器显示的时候因为采用了自定义的字体文件,所以显示正常。一大串字符串,从base64后面开始一直到后面format前面的括号中的内容,应该是字体文件的内容。是经过了base64编码后的形式。把这一段字符串考出来,用base64解码后再保存成本地ttf文件。

来源:老王的小船

环境:Win7Python3.6 Pycharm2017

目标:猫眼电影票房、汽车之家字体反爬的处理

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

http://www.w3school.com.cn/css3/css3_font.asp

一、猫眼电影

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

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

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

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

1import base6423font_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/HBzk8BY7hf2EmnSSQxk6VYYuDJ3Cu0SV9Y57V0tZKNZMm1HLzW 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'45b=base64.b64decode(font_face)6with open('zt02.ttf','wb')as f:7 f.write(b)

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

FontCreator安装:

安装包下载地址 :https:///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 就可以

基本命令介绍:

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

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

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

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

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

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

1from fontTools.ttLib import TTFont 2 3 4font1=TTFont('01.ttf') #打开本地字体文件01.ttf 5obj_list1=font1.getGlyphNames()[1:-1] #获取所有字符的对象,去除第一个和最后一个 6uni_list1=font1.getGlyphOrder()[2:] #获取所有编码,去除前2个 7 #手动确认编码和数字之间的对应关系,保存到字典中 8dict={'uniEA78': '8', 'uniF411': '2', 'uniE87C': '1', 'uniEAC3': '9', 'uniE9DA': '3', 'uniE06A': '4', 'uniE210': '0', 'uniED72': '7', 'uniECB8': '5', 'uniF2A9': '6'} 91011font2=TTFont('02.ttf') #打开访问网页新获得的字体文件02.ttf12obj_list2=font2.getGlyphNames()[1:-1]#公众号@老王的小船13uni_list2=font2.getGlyphOrder()[2:]1415for uni2 in uni_list2:16 obj2=font2['glyf'][uni2] #获取编码uni2在02.ttf中对应的对象17 for uni1 in uni_list1:18 obj1=font1['glyf'][uni1]19 if obj1==obj2:20 print(uni2,dict[uni1]) #打印结果,编码uni2和对应的数字

-----------分割线-------------

二、汽车之家

上面讲的猫眼电影例子,是编码变化,但是字体形状不变,网上也有很多介绍的文章。而汽车之家的字体反爬,不仅是编码变化,而且是字体形状也有变化。就是说对象本身变化,不能再直接用比较对象的方法处理。网上搜也是基本没什么好的解决办法,有一种是用OCR识别,这个当然可以。下面介绍一种博主自己摸索的方法,简单试了下应该是ok的。

先看问题,打开汽车之家论坛的一篇文章,https://club.autohome.com.cn/bbs/thread/1f05b4da4448439b/76044817-1.html###

右键检查,可以看到文章中的某些字符是显示不了的,如下图。

查找字体文件,直接html中搜索font-face,如下图,直接把url复制到浏览器中就能下载字体文件

再用FontCreator打开,一共有38个汉字采用了自定义字体。

上面说到汽车之家的字体形状也是变动的。直接打开字体文件看看是哪些数据发生了改变。其实主要有两个信息,一个是x,y坐标信息,还有一个是对应点0、1值。下几个字体文件就可以发现,同一个字符在不同的字体文件中x,y坐标是变化的,0,1值不变,还有坐标的数量也不变。

很容易可以联想到这些x,y坐标应该是用来描绘字体形状的,用pylab画个图可以看出,如下图。0,1估计是描述连线的参数。

这里猜想就是x,y坐标的变化是基于一个标准值做一定幅度的随机加减,而且这个范围相对于坐标系来说不会太大。因为变化太大的话字体显示就会有较大的差异,一个网站上的字符显示应该是保持一致的。实际通过几个字体文件计算得出的差值变化在40以内。

总结一下,这里我们要比较两个对象表示的字符是否相同,不能通过直接对比对象是否相等判断,而是要具体比较对象的坐标来判断。首先判断坐标的数量是否相同,如果相同的话,再比较每一个坐标是否相同,只要x,y相差40以内,我们就认为这2个坐标是相同的。如果两个对象的所有坐标都相同,则认为这两个对象表示同一个字符。这里有个前提就是同一个字符在不同字体文件中包含的x,y坐标数量是不变的,且x,y波动是在一定范围内的。实际测试几个样本来看这两个前提是满足的。还有就是两个不同字符误判成同一字符的概率,首先这38个字符坐标有29种数量,相同坐标数量的就没几个,还有每个坐标都差40以内是比较难碰撞的。还有为什么不用0,1来判断,这个值不同字符也有相同的。

具体实现:首先还是要在本地下载一个字体文件01.ttf,并手动确认好编码和字符的对应关系。然后重新访问网站时新加载的字体文件也下载到本地02.ttf,然后还是和上面的一样找到01中相同的对象并确认表示的字符。代码如下:

1from fontTools.ttLib import TTFont 2 3 4def comp(l1,l2): #定义一个比较函数,比较两个列表的坐标信息是否相同 5 if len(l1)!=len(l2): 6 return False 7 else: 8 mark=1 9 for i in range(len(l1)):10 if abs(l1[i][0]-l2[i][0])<40 and abs(l1[i][1]-l2[i][1])<40:11 pass12 else:13 mark=014 break15 return mark1617#手动确定一组编码和字符的对应关系18u_list=['uniEC1A', 'uniEC25', 'uniEC34', 'uniEC36', 'uniEC3F', 'uniEC50', 'uniEC6A', 'uniEC6C', 'uniEC86', 'uniEC98', 'uniECA0', 'uniECB2', 'uniECBC', 'uniECCC', 'uniECCE', 'uniECE8', 'uniECE9', 'uniECF9', 'uniED02', 'uniED04', 'uniED15', 'uniED1E', 'uniED2F', 'uniED49', 'uniED4B', 'uniED54', 'uniED65', 'uniED77', 'uniED7F', 'uniED81', 'uniED91', 'uniED9B', 'uniEDAD', 'uniEDC7', 'uniEDC8', 'uniEDE1', 'uniEDE3', 'uniEDFD']19word_list=['少','大','二','四','和','右','下','左','矮','十','得','远','很','九','的','长','坏','八','多','着','小','上','高','近','六','短','了','七','地','不','更','低','是','三','呢','一','好','五'] #公众号@老王的小船202122font1=TTFont('01.ttf')23be_p1=[] #保存38个字符的(x,y)信息24for uni in u_list:25 p1 = [] #保存一个字符的(x,y)信息26 p=font1['glyf'][uni].coordinates #获取对象的x,y信息,返回的是一个GlyphCoordinates对象,可以当作列表操作,每个元素是(x,y)元组27 # p=font1['glyf'][i].flags #获取0、1值,实际用不到28 for f in p: #把GlyphCoordinates对象改成一个列表29 p1.append(f)30 be_p1.append(p1)313233font2=TTFont('02.ttf')34uni_list2=font2.getGlyphOrder()[1:]35on_p1=[]36for i in uni_list2:37 pp1 = []38 p=font2['glyf'][i].coordinates39 for f in p:40 pp1.append(f)41 on_p1.append(pp1)424344n2=045x_list=[]46for d in on_p1:47 n2 =148 n1=049 for a in be_p1:50 n1 =151 if comp(a,d):52 print(uni_list2[n2-1],word_list[n1-1])53 x_list.append(word_list[n1-1])54#分行打印出来,方便和FontCreator中进行比较确认55print(x_list[:16])56print(x_list[16:32])57print(x_list[-6:])

运行结果:根据01找出02中编码和字符的对应关系,再用FontCreator打开02进行对比确认,结果OK 。

PS:博主实际测试了几个字体文件,都是OK的,但是也不保证全都OK。

最后,我自己是一名从事了多年开发的Python老程序员,辞职目前在做自己的Python私人定制课程,今年年初我花了一个月整理了一份最适合2019年学习的Python学习干货,可以送给每一位喜欢Python的小伙伴,想要获取的可以关注我的头条号并在后台私信我:01,即可免费获取。

,
    推荐阅读
  • 形成酸雨的主要气体是什么(形成酸雨的主要气体)

    以下内容大家不妨参考一二希望能帮到您!形成酸雨的主要气体是什么酸雨是指PH小于5.6的雨雪或其他形式的降水,形成的主要气体有二氧化硫、三氧化硫、硫化氢、二氧化氮。酸雨主要是人为的向大气中排放大量酸性物质所造成的。酸雨又分硝酸型酸雨和硫酸型酸雨。

  • 木棉花的花语是什么(木棉花的意义)

    接下来我们就一起去了解一下吧!珍惜眼前的幸福,珍惜身边的人给他们快乐与幸福。它的花期通常在3月或者4月份,在这一段时间盛开,而传说中四月的第十一天,是木棉花盛开的日子,所以4月11被定为木棉花的日子。

  • 炒凉皮不碎技巧(炒凉皮不碎有什么技巧)

    以下内容大家不妨参考一二希望能帮到您!炒凉皮不碎技巧炒凉皮不碎技巧:就是在做凉皮时不能炒太久,变软会失去筋度。胡萝卜切丝,蒜薹切段,葱切花,猪肉切丝,大蒜拍扁。成品凉皮一张张卷起切粗条,抖散备用。生抽,白糖,盐,鸡精,醋,胡椒粉调成汁备用。热锅倒适量食用油烧热加入大蒜,肉丝翻炒至金黄,加入胡萝卜丝和蒜薹炒熟,凉皮翻炒均匀后随即淋入调好的汁儿翻炒均匀。

  • 近几年灭绝的鱼(瞭望在长江源寻鱼)

    长江被誉为我国淡水渔业的摇篮、鱼类基因的宝库。据青海省渔业部门统计,长江流域青海段分布有土著鱼类21种。因此,严格意义上长江源的关键鱼类指的是裂腹鱼中的小头裸裂尻鱼。2019年,李伟带领团队参加长江源科考时,将小头裸裂尻鱼列为长江源鱼类研究的代表对象。2019年4月,科考小组五个人,两台车,开始了沿河寻觅之旅。“全球平均气温上升已是科学界的共识,位于青藏高原的长江源是全球气候变化的敏感区。”科考发现,江源地区

  • 鹧鸪在什么时候季节鸣叫(鹧鸪的孵化期有多长)

    鹧鸪在什么时候季节鸣叫鹧鸪一般会在繁殖季节鸣叫,繁殖期为3-6月,3-4月间开始求偶交配。求偶期间鸣叫更为频繁,常在山岩、树桩、灌木或乔木枝上鸣叫,尤以黎明和黄昏时更甚,往往是一鸟先鸣叫,其他雄鸟一起跟随,此起彼伏。鹧鸪的孵化期在21天左右,雏鸟出壳后不久即可跟随亲鸟活动。鹧鸪的繁殖期为每年的3-6月,3-4月间开始求偶交配,每窝产卵3-6枚,多时可达8枚,卵为椭圆形或梨形,颜色为淡皮黄色至黄褐色。

  • 秋天的诗词(这些都是关于秋天的诗句)

    迢迢新秋夕,亭亭月将圆《戊申岁六月中遇火》,今天小编就来说说关于秋天的诗词?《戊申岁六月中遇火》自古逢秋悲寂寥,我言秋日胜春朝。《秋词》是处红衰翠减,苒苒物华休。惟有长江水,无语东流。宋·柳永《八声甘州》落时西风时候,人共青山都瘦。《昭君怨》雨色秋来寒,风严清江爽。《酬裴侍御对雨感时见赠》秋声万户竹,寒色五陵松。唐·李颀《望秦川》秋色无远近,出门尽寒山。宋·苏轼《九日次韵王巩》

  • 广州有几种车牌(广州车牌你有吗)

    在广州的普通上班族,有房贷还想拥有一辆车,已经不容易了。但有车想让个广州牌,那更是难上加难,再加之限行,参与摇号,竞价的人是越来越多,那中标的机会更是渺茫了!截止日期是8日24时止。9月拟配置的中小客车增量指标共16313个,是这样分配的:1.以摇号方式向单位和个人配置节能车增量指标7285个,其中,单位指标100个,个人指标7185个。

  • qq注销账号有哪几个步骤(QQ将开注销帐号功能)

    1999年2月10日,一个名为OICQ、只有几百K的软件正式上线。当时,腾讯方面表示,这是QQ团队对帐号注销功能的灰度测试。网友截图出于安全考虑,也有网友表示支持有人说,QQ不推出注销服务有自己的考虑,这是为了防止用户QQ密码被他人知道后恶意注销,给用户带来无法挽回的损失。腾讯2018年第三季度财报显示,QQ智能终端月活跃账户同比增长6.9%至6.979亿。

  • 高跟鞋不合脚怎么办(穿高跟鞋不合脚怎么办)

    4、合理利用袜子,如果不喜欢垫各种鞋垫的朋友,可以穿一双船袜,再穿高跟鞋,那样既不影响穿着效果,也不影响美观,也是比较简单和实用的方法。

  • 年四旺名字打分104分 年四旺事迹

    文章目录:一、年四旺相关名字打分113二、年四旺相关名字评分115三、年四旺相关名字推荐四、年四旺相关名字大全五、其他人还看了一、年四旺相关名字打分113年灯石志明年橘纪红兵武尊道后书法孔多塞年贷款孙敬媛年立秋里蓝业珍冯景华年见朱诗词林于思冯桂年粤日林格孟昭毅年家薛邑马布鱼鲁初雪苏沫沫卜庆中年上年掌柜秦源达刘登龙严学锋国韵酒年线高成江裘梦年维泗红沙日年周王克斌王翔千毛淑红龙威信李万和年神范小慧王大