字体反爬之猫眼电影

暑假如约而至,暑期档电影究竟是谁能脱颖而出呢?

字体反爬之猫眼电影_第1张图片

目前看来是刚上映的银河补习班热度最高。但最后鹿死谁手还尚未可知,我们可以通过爬取猫眼的实时票房数据来一看究竟。

字体反爬之猫眼电影_第2张图片

通过观察网页源代码,我们发现,票房的数字变成了.而不是我们在网页上看到的6276.7。这个网站采取了字体反爬,这也是一种常见的反爬技术。网站采用了自定义的字体文件,内容能够在浏览器上正常显示,但是爬取的数据就变成了乱码,如同下图的小方框。

字体反爬之猫眼电影_第3张图片

采用自定义字体文件是CSS3的新特性,CSS3 @font-face中定义了字体,这个自定义字体文件存放到 web 服务器上,它会在需要时被自动下载到用户的计算机上,以便我们在访问网页时渲染出字体。

我们可以利用fontTools这个第三方库,来对这些字体文件进行操作。

from fontTools.ttLib import TTFont
font_1 = TTFont('a.woff')
font_1.saveXML('font_1.xml')

我们可以在xml中查看这个字体文件。也可以利用百度字体编辑器,导入相应woff文档,便能够查看对应字体。

既然如此,那我们只要建立相应的映射关系,不就能解密字体了吗?easy~

字体反爬之猫眼电影_第4张图片

经过观察发现,该字体文件每刷新一次页面都会发生更新,其name随着字体文件的变化而变化,这就令人有些头大了。

字体反爬之猫眼电影_第5张图片

别着急,我们来看看这个xml页面吧。借助百度字体编辑器,发现这个F496代表的是4,而另外一个字体文件中的E603代表的是4。

字体反爬之猫眼电影_第6张图片

我们在第一个xml中找到4,也就是F496,在第二个xml中也找4,即E603。

字体反爬之猫眼电影_第7张图片

字体反爬之猫眼电影_第8张图片

我们惊喜的发现这两个不同字体文件中对4的描述是完全一致的,仅仅是不同的字体文件它对4的命名不同,同时观察其他数字也能得到相同的结论。这样我们就找到了问题的关键,只要TTGlyph对象相同,它所表示的就是相同的数字。

我们可以先在本地存放一个base字体文件,这个字体文件中我们通过百度字体编辑器得到了一一对应关系。

font1=TTFont('./fonts/base.woff')
base_dict={'uniE18E': '3', 'uniE585': '2', 'uniE194': '9', 'uniF439': '4', 'uniE7DB': '7','uniF115': '0',
                'uniF0A4': '5', 'uniE311': '1', 'uniF7EF': '8', 'uniEACB': '6'}

再利用正则表达式从网页中下载到新的字体文件,并通过相同的字体对象构造新的映射关系,即新字体文件中定义的对象名与真实代表数字之间的对应关系。

response=requests.get(url,headers).text
# 正则匹配字体woff文件
font_file=re.findall(r'vfile\.meituan\.net\/colorstone\/(\w+\.woff)', response)[0]
url2='http://vfile.meituan.net/colorstone/' + font_file
new_file=requests.get(url2,headers)
with open('./fonts/'+font_file,'wb') as f:
    f.write(new_file.content)
font2=TTFont('./fonts/'+font_file)
# font2.saveXML('font_2.xml')
# 获取字符的name列表
name_list2=font2.getGlyphNames()[1:-1]
new_dict={}


for name2 in name_list2:
    obj2=font2['glyf'][name2]
    for name1 in name_list1:   
        obj1=font1['glyf'][name1]
            # 对象相等则说明对应的数字相同
            if obj1==obj2:
                new_dict[name2]=base_dict[name1]

在解决了字体反爬的问题之后,我们能利用requests库和各种解析的库在页面源代码中提取我们想要的信息了。

def get_info(response):
    '''
    输入:页面源码
    输出:包含电影票房等信息的字典列表    
    '''
    # Mongo配置
    conn=MongoClient('127.0.0.1', 27017)
    db=conn.maoyan                    #连接maoyan数据库,没有则自动创建
    mongo_my=db.film                  #使用film集合,没有则自动创建
    items=[]
    tree=etree.HTML(response)
    film_name=tree.xpath('//div[@class="movie-item-info"]/p/a/text()')
    booking_office_today=tree.xpath('//div[@class="movie-item-number boxoffice"]/p[@class="realtime"]/span/span/text()')
    booking_office_total=tree.xpath('//div[@class="movie-item-number boxoffice"]/p[@class="total-boxoffice"]/span/span/text()')
    a=tree.xpath('//div[@class="movie-item-number boxoffice"]/p[@class="realtime"]/text()')[1::2]
    b=tree.xpath('//div[@class="movie-item-number boxoffice"]/p[@class="total-boxoffice"]/text()')[1::2]
    for i in range(len(film_name)):
        item={'film_name':film_name[i],
              'booking_office_today':booking_office_today[i]+a[i].replace('\n',''),
              'booking_office_total':booking_office_total[i]+b[i].replace('\n',''),              
            }
        items.append(item)
        mongo_my.insert_one(item)       
    return items

字体反爬之猫眼电影_第9张图片

本文全部代码已上传至后台,详情请回复“猫眼”

                                                                           喜欢就点个赞吧❤

你可能感兴趣的:(字体反爬之猫眼电影)