美文网首页大数据 爬虫Python AI SqlPython3自学 爬虫实战
反爬虫解析-字体替换--天眼查/猫眼电影

反爬虫解析-字体替换--天眼查/猫眼电影

作者: 叫我老村长 | 来源:发表于2019-10-06 17:22 被阅读0次

    猫眼电影

    1. 打开猫眼电影详情页 http://maoyan.com/films/1198214,查看用户评分和累计票房,发现源码中是乱码。

      [图片上传失败...(image-dc93eb-1542801738027)]

    2. 他们的class都是 "stonefont" ,找到 "stonefont" 的定义。

        @font-face {
          font-family: stonefont;
          src: url('//vfile.meituan.net/colorstone/1881db7c788dfdf9d2d00a926734d0973168.eot');
          src: url('//vfile.meituan.net/colorstone/1881db7c788dfdf9d2d00a926734d0973168.eot?#iefix') format('embedded-opentype'),
               url('//vfile.meituan.net/colorstone/632958fd02509dc28d915375c3a835e02088.woff') format('woff');
        }
    
        .stonefont {
          font-family: stonefont;
        }
    
    
    1. 刷新几次,看到每次 url 是变化的,确定是动态生成字体,不要紧,生成哪个下载哪个。

    2. 加载一个页面,把这个字体文件下载下来拿去分析,可能是在文件中数字的地方进行了替换。在网上正好有一片是防止爬虫采集的文章: 利用自定义web-font实现数据防采集,看过后恍然大悟,这不正是我们要的吗,嘿嘿,爬虫是防不住的!

    3. 用 python 的 fonttools 库提取字体,fonttools 的用法可以网上查找一下

    pip3 install fonttools         # 安装
    
    
    1. 把 woff 的文件转换成我们熟悉的 xml 格式
    from fontTools.ttLib import TTFont     # 导包
    
    font = TTFont('./632958fd02509dc28d915375c3a835e02088.woff')    # 打开文件
    font.saveXML('./6329.xml')     # 转换成 xml 文件并保存
    
    
    1. 打开 xml 文件,红框内即为我们要的,略微不同,把 uni 改成 &#x ,后面再加一个分号 。

      [图片上传失败...(image-808429-1542801738027)]

    2. 跟源代码中对应验证一下可以得出他们的对应关系如下。

      [图片上传失败...(image-fb6eb3-1542801738027)]

    3. 用fonttools 可以直接从文件得到这些值

    from fontTools.ttLib import TTFont     # 导包
    
    font = TTFont('./632958fd02509dc28d915375c3a835e02088.woff')   # 打开文件
    gly_list = font.getGlyphOrder()     # 获取 GlyphOrder 字段的值
    for gly in gly_list[2:]:    # 前两个值不是我们要的,切片去掉
        print(gly)                 # 打印
    
    
    1. 最后补充完整代码
      思路:前面知道字体库是随机的,可以一些提前把能刷新到的下载到本地,抓取页面时,如果已经在本地,直接使用,不在的话再下载下来。
      本地目录:字体存在 fonts 目录下
    [图片上传失败...(image-df8c9a-1542801738027)]
    

    代码

    完整代码
    import requests
    import re
    import os
    from fontTools.ttLib import TTFont
    
    class MaoYan(object):
        def __init__(self):
            self.url = 'http://maoyan.com/films/1198214'
            self.headers = {
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36"
            }
    
        # 发送请求获得响应
        def get_html(self, url):
            response = requests.get(url, headers=self.headers)
            return response.content
    
        # 创建 self.font 属性
        def create_font(self, font_file):
            # 列出已下载文件
            file_list = os.listdir('./fonts')
            # 判断是否已下载
            if font_file not in file_list:
                # 未下载则下载新库
                print('不在字体库中, 下载:', font_file)
                url = 'http://vfile.meituan.net/colorstone/' + font_file
                new_file = self.get_html(url)
                with open('./fonts/' + font_file, 'wb') as f:
                    f.write(new_file)
    
            # 打开字体文件,创建 self.font属性
            self.font = TTFont('./fonts/' + font_file)
    
        # 把获取到的数据用字体对应起来,得到真实数据
        def modify_data(self, data):
            # 获取 GlyphOrder 节点
            gly_list = self.font.getGlyphOrder()
            # 前两个不是需要的值,截掉
            gly_list = gly_list[2:]
            # 枚举, number是下标,正好对应真实的数字,gly是乱码
            for number, gly in enumerate(gly_list):
                # 把 gly 改成网页中的格式
                gly = gly.replace('uni', '&#x').lower() + ';'
                # 如果 gly 在字符串中,用对应数字替换
                if gly in data:
                    data = data.replace(gly, str(number))
            # 返回替换后的字符串
            return data
    
        def start_crawl(self):
            html = self.get_html(self.url).decode('utf-8')
    
            # 正则匹配字体文件
            font_file = re.findall(r'vfile\.meituan\.net\/colorstone\/(\w+\.woff)', html)[0]
            self.create_font(font_file)
    
            # 正则匹配星级
            star = re.findall(r'<span class="index-left info-num ">\s+<span class="stonefont">(.*?)</span>\s+</span>', html)[0]
            star = self.modify_data(star)
    
            # 正则匹配评论的人数
            people = ''.join(re.findall(r'''<span class='score-num'><span class="stonefont">(.*?万)</span>(人评分)</span>''', html)[0])
            people = self.modify_data(people)
    
            # 正则匹配累计票房
            ticket_number = ''.join(re.findall(r'''<span class="stonefont">(.*?)</span><span class="unit">(亿)</span>''', html)[0])
            ticket_number = self.modify_data(ticket_number)
    
            print('用户评分: %s 星' % star)
            print('评分人数: %s' % people)
            print('累计票房: %s' % ticket_number)
    
    if __name__ == '__main__':
        maoyan = MaoYan()
        maoyan.start_crawl()
    
    

    相关文章

      网友评论

        本文标题:反爬虫解析-字体替换--天眼查/猫眼电影

        本文链接:https://www.haomeiwen.com/subject/yjgupctx.html