欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Python爬虫入门教程 63-100 Python字体反爬之一,没办法,这个必须写,反爬第3篇

程序员文章站 2022-07-05 14:19:15
背景交代 在反爬圈子的一个大类,涉及的网站其实蛮多的,目前比较常被爬虫coder欺负的网站,猫眼影视,汽车之家,大众点评,58同城,天眼查......还是蛮多的,技术高手千千万,总有五花八门的反爬技术出现,对于爬虫coder来说,干!就完了,反正也996了~ 作为一个系列的文章,那免不了,依旧拿猫眼 ......

背景交代

在反爬圈子的一个大类,涉及的网站其实蛮多的,目前比较常被爬虫coder欺负的网站,猫眼影视,汽车之家,大众点评,58同城,天眼查......还是蛮多的,技术高手千千万,总有五花八门的反爬技术出现,对于爬虫coder来说,干!就完了,反正也996了~

作为一个系列的文章,那免不了,依旧拿猫眼影视“学习”吧,为什么?因为它比较典型~

猫眼影视

打开猫眼专业版,常规操作,谷歌浏览器,开发者工具,抓取dom节点,

注意下图所有的数字位置,在dom结构中,都是方块。
Python爬虫入门教程 63-100 Python字体反爬之一,没办法,这个必须写,反爬第3篇

字体反爬扫盲

字体反爬,是一种常见的反爬技术,网站采用了自定义的字体文件,在浏览器上正常显示,但是爬虫抓取下来的数据要么就是乱码,要么就是变成其他字符。采用自定义字体文件是css3的新特性,熟悉前端的同学可能知道,就是font-face属性

一些重要破解素材的收集

找到font-family属性,查看设置的内容,发现是cs字体,这明显是自定义字体了,在网页中检索cs
Python爬虫入门教程 63-100 Python字体反爬之一,没办法,这个必须写,反爬第3篇
在页面的html源码中找到了字体的定义
Python爬虫入门教程 63-100 Python字体反爬之一,没办法,这个必须写,反爬第3篇
注意文件的开头是base64 表示文件进行过base64编码,需要进行解码,然后在保存成ttf字体文件

上述截图中有个woff格式

web开放字体格式(web open font format,简称woff) 是一种网页所采用的字体格式标准。此字体格式发展于2009年,现在正由万维网联盟的web字体工作小组标准化,以求成为推荐标准。此字体格式不但能够有效利用压缩来减少档案大小,并且不包含加密也不受drm(数位著作权管理)限制。

解码操作

import base64

font_face = "d09grgabaaaaaaggaasaaaaac7gaaqaaaaaaaaaaaaaaaaaaaaaaaaaaaabhu1vcaaabcaaaadmaaabcsp6z7u9tlziaaae8aaaaraaaafzw7lavy21hcaaaayaaaac8aaacta/vlrxnbhlmaaacpaaaa5eaaaq0l9+jtwhlywqaaaxqaaaalwaaadyuwblkaghlyqaabgaaaaacaaaajaekazlobxr4aaaghaaaabiaaaawghwaagxvy2eaaaywaaaaggaaabof2gtmbwf4caaabkwaaaafaaaaiaezadxuyw1laaagbaaaavcaaakfkahoc3bvc3qaaafeaaaaxaaaai/gskzlejxjygrgyobikgpqywb0cfmjyebgyggaajamy05meijqdmodyrgaaq4gzooiagckiwnpahicy2bk0mwcwmdkwmhuyxsggyghh0izvmywyurgygbiygvmwaoc0lxtgbwykr7lmev812giydzhuaiuzgtjaqdzjgsnejzfkj0ogzamhv8kpt906nije3thuigrsll0bd1fxk5doac3iegkjeywrvoss1sctxx0rbid+vl2aowbroroykc9oedtxagk8qjnei/xoh/dlzejkpmb3vnbuto1ftkuo56yeeal7cyakvzcoz6tuole9r0o7dolqu8w2aj0a1p/k/62s7ifi5esaoetmlzg/gc04hfcwyezhw0fv1txc5wzxcnw4uhlwf+rorc81qgf7gntjid+antorpr4newtz2/azhzg39duocwekghjqlramnggkudy2arwdmwbnj8zcrbcwhqiltjsbboo6di22lr2q2qn/qhdzdiou1q79n5j03raoru59a+o1otum9rlrpbaizkpr/s+0vs+n+f7payqgmo/gqgigagqkejcr/aafdbcdrgxwawas6zjhww34owge0ocltg4z+jtksvttwahnp60l0tjtyr5uppeg2z9k0hl3b2dvmsijzdznqpsl2adawdqmi1daugigzibskc9+ycsxgw2a++eleb+vyg9o0bnvx7do/wxa9gbwiayivnbsus6gpyccc6kw5kgk8cvsfrbknbajsixhiyztnbkeprbvl7rv4vimnnyceijjszw73+5mb2jpu8wk3hfbttlk+lqohkv+isqj2iyvxnuo2wnel0pn29+m/d958lplffybabnvxulhxb05f957caeo3lbddkglputkobolddmzyah+f4kjvhuzyuoegtq6a7ycar7hfh7dhqteedcnenjgjpwk4thbdf/a5trsrwqhtwj5ty82n3pbaazxqnk/vonka3vzt638btk+m1wq/ybm3p0ff3iijjzp+b6glhcaiyqddyhwqysyyunghpwhpgiboghltdvg+atbkpihufuzdysn959vuthcv3greqjvnlz7/peynjamd03ew1mtmbr3diujc2ivianx85qaz1f/6buvahre18cksmtlkjipwelgdkhfbbpgxkzgxgdwqukvuhcqjdkcyrxm4o0bas5k6lyspyqxynmhcftk3un/5jlvfc43rya01ncrssn1mmt3jo19tn34kxc5a+26uc4h7clgajgfcgxjodhk+zn1wgf6oij4aygyxiiuqav/manq/fiielzbwjr0spe6mru1pn5/bokitu7t7k8q5skd8uyo06nup7kuwvlyrzt0u9m/fhiv7ekjje7r0yr0frczeovwe56sqcux9c/yvtsznw0jajf+wthlkqjk6dvqrgptfgods8/3xqxvznld96ezxaexfxgal11/mxwjbgosgs4/eujfs1vfnzj9nybd1/jxd7t1gah8xm8e/a39gz3mzcnxctbpvwqnczkomccxkgl0dtfa4drm0qikk6orbokelztxe30waft7hi+vryufuql+8sr/kfoddy7s4vltuhwvzlpcyvls7vxz+/swpv0ssqb/wagjodcaaaaejxjygrgyadixsuwzy3nt/nkwm3caai3llqdrnd/37awmj0hcjkymeciagamdgeaejxjygrgynb5r8mqw8iaakcskqev8aaam2ibzxicy2eaghqgbiyd4jaan4wcnqaaaaaaaaamadaatacuak4a4aeaavwboahmahoaahicy2bkygdgytbgygyaasyg5gjcbob/yd4daa6davyaejxlkbtuwkaurmc88gapqomujoq0tdiqzeopudokkcnr0buzbio/tf6qsjcpyhfle9klyyekz2cug8cr7547m3d9jqo4xjccnj57vid2cmhqxdwc40g4tv1juef+fm6ijrfhm+oz4ra6ebvu4wzvvmfpxlia40pyqqefwjvc4uu4tv1hueh+fw7i1mkkn6hj3am3shc6wm08ou8tpszge1av1pkggjsxpd8zjtsgtuinyvga6/uu8kxzludcmzxmezv0b6u004k25w35fj2ynlcbswm1paujkfwzsbfat+7g2mzc7weiu34aczzfnygbhgflfcv6iqp3acksaj349axxsn9it0j16jepob01doikbnwt1ovippz6svyywsxgx2rgvfikq7pl2pnri6qw6eoshj0xasq9mpneziws8lzufoounkvxxp/d5woqebeyif4d2j1ywqb4ng2koxkaibbdn/hbee8iokalkt7fxs4zj++4tkz5k7yqobxf/9eqkfciqg2jbi0uomj0hefe15ng2tchgd8ewstuwye8u+zhdwdv8y/z5jhuw5jrt0qvgvqxkq=="

print(len(font_face))

b = base64.b64decode(font_face)
with open('font.ttf','wb') as f:
    f.write(b)

对于ttf文件的处理,有3种方式,第一种使用软件 fontcreator可以直接打开ttf文件,第二种使用python第三方库fonttools,借用这个库也可以操作ttf文件,第三种使用百度的fontstore,

fontcreator 软件查找这个就比较简单了

你可以自行百度寻找,也可以直接打开我的百度网盘下载

链接: https://pan.baidu.com/s/1zywwk37hneo0vistqdk2fg 提取码: kk2h

安装完毕,直接试用即可,也可以采用国家支持的和谐方法,进行和谐
Python爬虫入门教程 63-100 Python字体反爬之一,没办法,这个必须写,反爬第3篇
查阅一下sources里面的html编码

Python爬虫入门教程 63-100 Python字体反爬之一,没办法,这个必须写,反爬第3篇
数字进行比对
Python爬虫入门教程 63-100 Python字体反爬之一,没办法,这个必须写,反爬第3篇
顺便把这个地方的编码对应关系记录一下,方便后续操作

'unie481': '7',
'unie0aa': '4', 
'unif71e': '9', 
'unie767': '1', 
'unie031': '5', 
'unie4bd': '2',
'unif2aa': '3',
'unie2e3': '6', 
'unie3c9': '8', 
'uniea65': '0'

数字比对完全没有问题3.69亿
Python爬虫入门教程 63-100 Python字体反爬之一,没办法,这个必须写,反爬第3篇

开始编码破解字体反爬

有的网页嵌套了多套字体,增加了反爬的成本,届时自行研究即可

利用fonttools可以获取每一个字符对象,这个对象你可以简单的理解为保存着这个字符的形状信息。
而且编码可以作为这个对象的id,具有一一对应的关系。
类似猫眼电影,多套字体对应的字符的编码是变化的,但是字符的形状是不变的,也就是说这个对象是不变的。

通过fonttools进行解析字库文件

安装fonttools

pip install fonttools

fonttools库详解:

基本使用

from fonttools.ttlib import ttfont

font = ttfont('font.ttf')
font.savexml('01.xml')

打开 xml 文件

开头显示的是全部编码,注意这里的id是编号,千万不要当成对应的数字
Python爬虫入门教程 63-100 Python字体反爬之一,没办法,这个必须写,反爬第3篇
下面对应的是字体信息,计算机只需要知道黑白像素点即可
Python爬虫入门教程 63-100 Python字体反爬之一,没办法,这个必须写,反爬第3篇
注意事项,写代码的时候需要注意一下
Python爬虫入门教程 63-100 Python字体反爬之一,没办法,这个必须写,反爬第3篇
Python爬虫入门教程 63-100 Python字体反爬之一,没办法,这个必须写,反爬第3篇

关于猫眼的字体反爬做个总结

在实操中,你会发现猫眼电影,每次刷新字符编码都是变化的,但是字体的对象,也就是像素点是一致的。
Python爬虫入门教程 63-100 Python字体反爬之一,没办法,这个必须写,反爬第3篇
你可以通过第一次下载一个字体文件base_font.ttf,并把对应编码的记下来,当第二次刷新页面之后,重新抓取字体文件online_font.ttf ,对比两个字体文件中的对象信息,如果对象是一样的,那么就可以知道对应的数字了。

首次获取字体文件

# 本地已经下载好的字体处理
base_font = ttfont('font.ttf') #打开本地的ttf文件

base_uni_list = base_font.getglyphorder()[2:]   # 获取所有编码,去除前2个,可查看前文图示

# 写出第一次字体文件的编码和对应字体
origin_dict = {'unie481': '7', 'unie0aa': '4', 'unif71e': '9', 'unie767': '1', 'unie031': '5', 'unie4bd': '2','unif2aa': '3', 'unie2e3': '6', 'unie3c9': '8', 'uniea65': '0'}

获取在线字体

# 获取刷新之后在线的字体

# 获取字体文件的base64编码
online_ttf_base64 = re.findall(r"base64,(.*)\) format", response)[0]
online_base64_info = base64.b64decode(online_ttf_base64)
with open('online_font.ttf', 'wb')as f:
    f.write(online_base64_info)
online_font = ttfont('online_font.ttf')  # 网上动态下载的字体文件。

online_uni_list = online_font.getglyphorder()[2:]


for uni2 in online_uni_list:
    obj2 = online_font['glyf'][uni2]  # 获取编码uni2在online_font.ttf中对应的对象
    for uni1 in base_uni_list:
        obj1 = base_font['glyf'][uni1]  # 获取编码uni1在base_font.ttf 中对应的对象
        if obj1 == obj2:  # 判断两个对象是否相等
            dd = "&#x" + uni2[3:].lower() + ';'  # 修改为unicode编码格式
            if dd in response:  # 如果编码uni2的unicode编码格式 在response中,替换成origin_dict中的数字。
                response = response.replace(dd, origin_dict[uni1])

response的获取采用的是request模块

url = 'https://piaofang.maoyan.com/?ver=normal'
headers = {
    'user-agent': '浏览器ua',
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
}
response = requests.get(url=url, headers=headers).content  # 得到字节
charset = chardet.detect(response).get('encoding')  # 得到编码格式
response = response.decode(charset, "ignore")  # 解码得到字符串

运行结果展示

Python爬虫入门教程 63-100 Python字体反爬之一,没办法,这个必须写,反爬第3篇
关注微信公众账号:非本科程序员,回复0409获取下载地址

Python爬虫入门教程 63-100 Python字体反爬之一,没办法,这个必须写,反爬第3篇