FontCreator
我们用Chrome登录电影《死侍2》的主页,查看页面信息,会发现用户评分出现乱码两个方框:
再查看这个地方的html源代码:
是类似一个引用。这明显使用了某种反爬技术。
另外大家可以自行验证,这里的引用的16进制的编号,每次访问都是不一样的(或者是过几分钟再访问),同一个数每次访问可能对应不同的编号。
这其实是使用的css3的新特性,继续查看源代码可以发现html中有这一段:
简单点理解就是,它这里的评分数字是用的图标的形式(iconfont),即在请求页面信息的同时,请求了一个字体文件(就是上图的那个请求woff的url),然后根据源码中的16进制编号,找到这个文件中对应的字体对象,再显示给用户。同时,每次请求的这个woff和评分位置的16进制编号并不唯一,意思就是说,它这个woff是动态的(即数字对象的编号是动态的),只要每次16进制的编号和woff文件中的对应就可以,这样实现了反爬的效果。
通过验证,会发现woff中数字对应的字体对象是不变的,只是每次访问的数字的编号在变化。(验证过程无非就是用fontTools.ttLib库中的TTFont.(“×××.woff”).saveXML(“×××.xml”),将woff保存为xml,打开亲自比对一下每个数的配置)
(至于iconfont的使用也非常简单,可以在https://www.iconfont.cn/下载几个矢量图标试一下。这里和爬虫没什么关系,就不再介绍。)
对此我们可以想到下面的策略:
1、首先我先下载了一个woff文件,用FontCreator打开
这就作为基准的对应
2、为了方便演示,我打开另一部电影的主页,同时下载这个主页捆绑的woff文件,并记录它的评分及编号
它的编号为、,分别是9、4
注意:这里的编号在各个地方的前缀不一致,代码中需要处理一下
在这里看到的是
爬下来的html为\u
在woff中为uni
3、代码
from fontTools.ttLib import TTFont
base_num = dict() # 编号—数字
base_obj = dict() # 编号—对象
def init():
# 注意,这里的编号与上面说的是一致的,只是前缀不一样,网页上看的是 ,爬下来的是\u,需要处理一下
base_num["uniF290"] = "0"
base_num["uniEA12"] = "1"
base_num["uniED86"] = "2"
base_num["uniED0D"] = "3"
base_num["uniE60A"] = "4"
base_num["uniEF1F"] = "5"
base_num["uniEEBA"] = "6"
base_num["uniEC5B"] = "7"
base_num["uniF01B"] = "8"
base_num["uniF6B0"] = "9"
# 打开基准的woff文件
BaseFontfile = TTFont('d2f5f7d50623609613eb8c0cddf472ac2080.woff')
for key in base_num:
base_obj[key] = BaseFontfile['glyf'][key] # 获得woff内编号对应的字体对象
def getRealNum(HexNum,woffFileName):
fontFile = TTFont(woffFileName)
obj = fontFile['glyf'][HexNum]
for key in base_obj: # 遍历找到相同的字体对象
if obj == base_obj[key]:
return base_num[key]
if __name__ == '__main__':
init()
print(getRealNum("uniE8DA","9f14db7a2613e566981242118676d9d72080.woff"))
print(getRealNum("uniF587", "9f14db7a2613e566981242118676d9d72080.woff"))