爬虫高级内容,Python如何应对字体反爬
在编写网页爬虫的时候,我们经常会遇到各种反爬,比如js加密、css位置偏移、字体反爬等。最近在学习过程中,我碰到几个网站,都是使用的字体反爬,其大致上可以分为两类:一类是字体文件是静态的,另一类字体文件是动态的变化的。今天,我们探究一下,在爬虫中如何破解字体反爬。
一、如何寻找字体文件字体文件大致上分两种,一种是以.ttf结尾的,一种是以.woff结尾的,两者相差不大,现在的网站运用的大多是woff文件。如何寻找网页使用的字体文件,可以分两类:
1.第一类 字体URL在网页源代码中以aHR0cHM6Ly93d3cucmVucmVuY2hlLmNvbS9iai9lcnNob3VjaGUvP3Bsb2dfaWQ9NWI5NzA3MWI1YjVhNWZkYWRkOWZhZDEzMGE0MmJiMDM=网站为例:
打开网站后,明显能看到,8被替换成了6。这种情况,我们可以尝试在网页源代码中搜索“font-face”,查看字体URL。
2.第二类 字体URL不在网页源代码中,由服务器加载以aHR0cHM6Ly93d3cuZ3VhemkuY29tL2J1eQ==网站为例:
这里可以看到车辆的行使里程数和首付均是字体反爬,按照第一种情况,我们直接在网页源代码中搜索“font-face”
可以看到,也是有woff文件和ttf文件,但这两个文件都是“element-icons”的链接,打开(软件:FontCreator)后也就是一堆图标。
遇到这种的,可以打开浏览器Network,刷新后抓包。
可以看到这个请求返回的结果中有一个woff文件,打开后观察:
这个正是我们要找的字体文件,当然这个网站要拿到字体URL需要js逆向verify-token这个参数,这里不展开说。
二、如何应对静态字体反爬还是以aHR0cHM6Ly93d3cucmVucmVuY2hlLmNvbS9iai9lcnNob3VjaGUvP3Bsb2dfaWQ9NWI5NzA3MWI1YjVhNWZkYWRkOWZhZDEzMGE0MmJiMDM=网站为例,经过观察,他的字体是每天更换一次,暂且当作是静态。
1.在网页源代码中搜索字体文件的URL,复制到浏览器中打开,下载字体文件。2.用FontCreator打开文件,查看字体对应关系,手动建立对应关系字典。#字体对应关系relation_table={"zero":"0","one":"2","two":"1","four":"3","three":"4","five":"8","seven":"7","nine":"9","six":"6","eight":"5"}
这是我学习过程中自己手动建立的对应关系。
3.请求字体链接,获取字体code和name的对应关系,然后遍历,获取网页中反爬文字的真实文字。defwoff_font(font_url):"""获取字体真实对应关系"""newmap={}resp=session.get(font_url)#请求字体链接woff_data=BytesIO(resp.content)font=TTFont(woff_data)#读取woff数据cmap=font.getBestCmap()#获取字体对应关系font.close()fork,vincmap.items():value=vkey=str(k-48)#获取真实的keytry:get_real_data=relation_table[value]except:get_real_data=""ifget_real_data!="":newmap[key]=get_real_data#将字体真实结果对应returnnewmap4.替换网页中的反爬文字
如果反爬字体是10进制或16进制的建议直接替换网页代码中的字体,如果是数字的,建议逐项替换。替换的方式有用正则表达式的(这里不说,因为我正则写的也不好),也有用列表推导式的,比如:
title="".join(html.xpath("//*[@id="zhimaicar-detail-header-right"]/div[1]/h1/text()")).strip()#获取原始标题trans_title="".join([iifnoti.isdigit()elsefont[i]foriintitle])#替换错误字体,获取真实标题
具体的用法,可以百度。
三、如何应对动态字体反爬动态字体反爬,就是每请求一次(或一段时间后),字体的映射关系也会改变,因为第二个网站比较麻烦,这个还是以这个网站为例,将时间节点放大,把他看做是动态反爬的。
1.先下载字体文件2.安装fontTools安装后用
fromfontTools.ttLibimportTTFontfont=TTFont(下载的字体文件)font.saveXML(文件名.xml)
将字体文件另存为xml文件,打开文件后会看到:
‘cmap’里存放的是字体code和name的关系
‘glyf’里存放的是字体形状和name的关系
3.手动建立字体形状和name的关系只需手动建立一次。
f_font=TTFont("rrcttf3d6e374d48fb2cd14247257d4ae76674.woff")#读取分析的字体文件f_font_glyf=f_font["glyf"]#获取分析文件中的字体关系#建立基础的字体和字体形状的对应关系base_font_map={0:f_font_glyf["zero"],1:f_font_glyf["two"],2:f_font_glyf["one"],3:f_font_glyf["four"],4:f_font_glyf["three"],5:f_font_glyf["eight"],6:f_font_glyf["six"],7:f_font_glyf["seven"],8:f_font_glyf["five"],9:f_font_glyf["nine"],}4.请求网页中的字体URL,获取code和name,形状和name的关系
resp=session.get(font_url)#请求字体链接woff_data=BytesIO(resp.content)#保存字体数据font=TTFont(woff_data)#读取woff数据glyf=font["glyf"]#获取请求到的字体形状code_name_map=font.getBestCmap()#获取请求到的字体code和name的对应关系font.close()5.根据形状相同,肯定字体相同的原则,获取真实对应关系
forcode,nameincode_name_map.items():codestr=str(code-48)#根据分析结果需要减去48current_shape=glyf[name]#根据name获取字体形状fornumber,shapeinbase_font_map.items():#遍历基础字体形状对应关系ifshape==current_shape:#判断,如果两个字体形状相等newmap[codestr]=str(number)#将字体编码和字体添加到字典6.完整代码
defwoff_font(font_url):newmap={}f_font=TTFont("rrcttf3d6e374d48fb2cd14247257d4ae76674.woff")#读取分析的字体文件f_font_glyf=f_font["glyf"]#获取分析文件中的字体关系#建立基础的字体和字体形状的对应关系base_font_map={0:f_font_glyf["zero"],1:f_font_glyf["two"],2:f_font_glyf["one"],3:f_font_glyf["four"],4:f_font_glyf["three"],5:f_font_glyf["eight"],6:f_font_glyf["six"],7:f_font_glyf["seven"],8:f_font_glyf["five"],9:f_font_glyf["nine"],}resp=session.get(font_url)#请求字体链接woff_data=BytesIO(resp.content)#保存字体数据font=TTFont(woff_data)#读取woff数据glyf=font["glyf"]#获取请求到的字体形状code_name_map=font.getBestCmap()#获取请求到的字体code和name的对应关系font.close()forcode,nameincode_name_map.items():codestr=str(code-48)#根据分析结果需要减去48current_shape=glyf[name]#根据name获取字体形状fornumber,shapeinbase_font_map.items():#遍历基础字体形状对应关系ifshape==current_shape:#判断,如果两个字体形状相等newmap[codestr]=str(number)#将字体编码和字体添加到字典returnnewmap7.结果验证
当我在写这篇分享的时候,该网站的字体早已经换了,但是建立关系的时候我还用的是之前的文件,可见返回的结果也是没有问题的。
四、总结静态字体反爬不用多说,面对动态反爬,一开始我也有点懵,后来在翻阅了一些资料和别人的启发后才弄明白,其实就是利用形状一样,字体肯定也一样的对应关系去破解。这是我学习过程中的一点经验总结,有不足之处还请各位指正,谢谢。
最后,推荐蚂蚁老师的视频套餐课程,包含爬虫部分,给我很大的帮助:
相关阅读
-
世界热推荐:今晚7:00直播丨下一个突破...
今晚19:00,Cocos视频号直播马上点击【预约】啦↓↓↓在运营了三年... -
NFT周刊|Magic Eden宣布支持Polygon网...
Block-986在NFT这样的市场,每周都会有相当多项目起起伏伏。在过去... -
环球今亮点!头条观察 | DeFi的兴衰与...
在比特币得到机构关注之后,许多财务专家预测世界将因为加密货币的... -
重新审视合作,体育Crypto的可靠关系才能双赢
Block-987即使在体育Crypto领域,人们的目光仍然集中在FTX上。随着... -
简讯:前端单元测试,更进一步
前端测试@2022如果从2014年Jest的第一个版本发布开始计算,前端开发... -
焦点热讯:刘强东这波操作秀
近日,刘强东发布京东全员信,信中提到:自2023年1月1日起,逐步为...