python爬取猫眼电影评分反反爬方式

一、所需工具

FontCreator

二、问题引入

我们用Chrome登录电影《死侍2》的主页,查看页面信息,会发现用户评分出现乱码两个方框:
python爬取猫眼电影评分反反爬方式_第1张图片再查看这个地方的html源代码:
python爬取猫眼电影评分反反爬方式_第2张图片是类似一个引用。这明显使用了某种反爬技术。
另外大家可以自行验证,这里的引用的16进制的编号,每次访问都是不一样的(或者是过几分钟再访问),同一个数每次访问可能对应不同的编号。

三、解决问题

这其实是使用的css3的新特性,继续查看源代码可以发现html中有这一段:
python爬取猫眼电影评分反反爬方式_第3张图片简单点理解就是,它这里的评分数字是用的图标的形式(iconfont),即在请求页面信息的同时,请求了一个字体文件(就是上图的那个请求woff的url),然后根据源码中的16进制编号,找到这个文件中对应的字体对象,再显示给用户。同时,每次请求的这个woff和评分位置的16进制编号并不唯一,意思就是说,它这个woff是动态的(即数字对象的编号是动态的),只要每次16进制的编号和woff文件中的对应就可以,这样实现了反爬的效果。

通过验证,会发现woff中数字对应的字体对象是不变的,只是每次访问的数字的编号在变化。(验证过程无非就是用fontTools.ttLib库中的TTFont.(“×××.woff”).saveXML(“×××.xml”),将woff保存为xml,打开亲自比对一下每个数的配置)

(至于iconfont的使用也非常简单,可以在https://www.iconfont.cn/下载几个矢量图标试一下。这里和爬虫没什么关系,就不再介绍。)

对此我们可以想到下面的策略:

  • 下载一个基准的woff文件a.woff(可以理解为woff文件中保存了编号与数字字体对象的对应),通过FontCreator工具打开,手动记录其中的编号与数字的对应关系,这时,就捆绑了 基准的 “编码—数字的字体对象—数字
  • 下载第二个woff文件b.woff和对应页面的编号,在代码中通过编号拿到了b.woff中对于的数字的字体对象,用这个对象依次与基准的十个字体对象比较,找到相同的一个,对应的基准数字及正确的数字。

四、代码实现

1、首先我先下载了一个woff文件,用FontCreator打开
python爬取猫眼电影评分反反爬方式_第4张图片这就作为基准的对应

2、为了方便演示,我打开另一部电影的主页,同时下载这个主页捆绑的woff文件,并记录它的评分及编号
python爬取猫眼电影评分反反爬方式_第5张图片python爬取猫眼电影评分反反爬方式_第6张图片python爬取猫眼电影评分反反爬方式_第7张图片它的编号为、,分别是9、4
注意:这里的编号在各个地方的前缀不一致,代码中需要处理一下
在这里看到的是&#x
爬下来的html为\u
在woff中为uni
3、代码

from fontTools.ttLib import TTFont
base_num = dict()  # 编号—数字
base_obj = dict()  # 编号—对象
def init():
    # 注意,这里的编号与上面说的是一致的,只是前缀不一样,网页上看的是 &#x,爬下来的是\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"))

python爬取猫眼电影评分反反爬方式_第8张图片

你可能感兴趣的:(python)