字体加密?看我如何破解某点评反爬逻辑!

本文就来好好聊一下如何破解字体加密,拿到我们想要的数据!

以爬取商家地址数据为例,我们打开大众点评网定位合肥,并搜索沙县小吃,之后在跳转的搜索结果页面中按下F12

现在定位到任一商家的地址,如上图所示,查看地址部分对应的源码发现,这部分的文字被包在svgmtsi标签中,并且大多数的字都是方框,根据文字长度我们不难判断出来,每一个小标签对应了一个文字,很明显,该网站对字体进行了加密!

所以下一步的任务很明确了「破解这个小方块

既然是字体加密,我们找到对应的字体

发现地址部分的字体是定义在CSS文件中,进一步点击打开对应的css文件

可以看到使用的是名为1d742900.woff字体文件,不管这个字体文件有多么神秘,既然给了地址,我们将它下载下来并打开(Windows下可以使用FontCreator等字体软件,当然也有很多在线的字体编辑软件)

可以看到这份字体一共有603个glyphs,并且每一个字有唯一对应的unicode编码

现在我们查看地址部分源码

接着使用requests请求该页面并提取第一个地址对应的文字信息

我们可以发现,除了未被加密的文字,所有加密的文字都以unicode编码记录,并且这个源码与我们上面打开的字体文件对应,不信我们验证一下,第一个被加密的文字为路

请求得到的编码为\uef66,我们回去字体文件中查找

后四位刚好与\uef66对应!

所以接下来我们的思路就非常明确了,建立文字与编码的映射也就是说,将这603个字转换为编码,再用这个编码去匹配被加密的文字

不过由于这603个字是在字体文件中无法直接导出,因此不论我们是用手敲还是OCR识别,都比较麻烦,幸运的是网上有人已经将这些字体整理出来了,所以我们直接拿来用即可!

下一步就是使用fontTools这个包解析woff文件,并构建后面匹配用到的字典,代码如下:

from fontTools.ttLib import TTFont
    
font = TTFont(font_name)
font1=font.getGlyphOrder()[2:] #解析字体
font1 = [font1[i][-4:] for i in range(len(font1))] #取最后四位编码

font2 = ['1', '2', '3', '4', '5', '6', '7', '8',
    '9', '0', '店', '中', '美', '家', '馆', '小', '车', '大',
    '市', '公', '酒', '行', '国', '品', '发', '电', '金', '心',
    '业', '商', '司', '超', '生', '装', '园', '场', '食', '有',
    '新', '限', '天', '面', '工', '服', '海', '华', '水', '房',
    '饰', '城', '乐', '汽', '香', '部', '利', '子', '老', '艺',
    '花', '专', '东', '肉', '菜', '学', '福', '饭', '人', '百',
    '餐', '茶', '务', '通', '味', '所', '山', '区', '门', '药',
    '银', '农', '龙', '停', '尚', '安', '广', '鑫', '一', '容',
    '动', '南', '具', '源', '兴', '鲜', '记', '时', '机', '烤',
    '文', '康', '信', '果', '阳', '理', '锅', '宝', '达', '地',
    '儿', '衣', '特', '产', '西', '批', '坊', '州', '牛', '佳',
    '化', '五', '米', '修', '爱', '北', '养', '卖', '建', '材',
    '三', '会', '鸡', '室', '红', '站', '德', '王', '光', '名',
    '丽', '油', '院', '堂', '烧', '江', '社', '合', '星', '货',
    '型', '村', '自', '科', '快', '便', '日', '民', '营', '和',
    '活', '童', '明', '器', '烟', '育', '宾', '精', '屋', '经',
    '居', '庄', '石', '顺', '林', '尔', '县', '手', '厅', '销',
    '用', '好', '客', '火', '雅', '盛', '体', '旅', '之', '鞋',
    '辣', '作', '粉', '包', '楼', '校', '鱼', '平', '彩', '上',
    '吧', '保', '永', '万', '物', '教', '吃', '设', '医', '正',
    '造', '丰', '健', '点', '汤', '网', '庆', '技', '斯', '洗',
    '料', '配', '汇', '木', '缘', '加', '麻', '联', '卫', '川',
    '泰', '色', '世', '方', '寓', '风', '幼', '羊', '烫', '来',
    '高', '厂', '兰', '阿', '贝', '皮', '全', '女', '拉', '成',
    '云', '维', '贸', '道', '术', '运', '都', '口', '博', '河',
    '瑞', '宏', '京', '际', '路', '祥', '青', '镇', '厨', '培',
    '力', '惠', '连', '马', '鸿', '钢', '训', '影', '甲', '助',
    '窗', '布', '富', '牌', '头', '四', '多', '妆', '吉', '苑',
    '沙', '恒', '隆', '春', '干', '饼', '氏', '里', '二', '管',
    '诚', '制', '售', '嘉', '长', '轩', '杂', '副', '清', '计',
    '黄', '讯', '太', '鸭', '号', '街', '交', '与', '叉', '附',
    '近', '层', '旁', '对', '巷', '栋', '环', '省', '桥', '湖',
    '段', '乡', '厦', '府', '铺', '内', '侧', '元', '购', '前',
    '幢', '滨', '处', '向', '座', '下', '県', '凤', '港', '开',
    '关', '景', '泉', '塘', '放', '昌', '线', '湾', '政', '步',
    '宁', '解', '白', '田', '町', '溪', '十', '八', '古', '双',
    '胜', '本', '单', '同', '九', '迎', '第', '台', '玉', '锦',
    '底', '后', '七', '斜', '期', '武', '岭', '松', '角', '纪',
    '朝', '峰', '六', '振', '珠', '局', '岗', '洲', '横', '边',
    '济', '井', '办', '汉', '代', '临', '弄', '团', '外', '塔',
    '杨', '铁', '浦', '字', '年', '岛', '陵', '原', '梅', '进',
    '荣', '友', '虹', '央', '桂', '沿', '事', '津', '凯', '莲',
    '丁', '秀', '柳', '集', '紫', '旗', '张', '谷', '的', '是',
    '不', '了', '很', '还', '个', '也', '这', '我', '就', '在',
    '以', '可', '到', '错', '没', '去', '过', '感', '次', '要',
    '比', '觉', '看', '得', '说', '常', '真', '们', '但', '最',
    '喜', '哈', '么', '别', '位', '能', '较', '境', '非', '为',
    '欢', '然', '他', '挺', '着', '价', '那', '意', '种', '想',
    '出', '员', '两', '推', '做', '排', '实', '分', '间', '甜',
    '度', '起', '满', '给', '热', '完', '格', '荐', '喝', '等',
    '其', '再', '几', '只', '现', '朋', '候', '样', '直', '而',
    '买', '于', '般', '豆', '量', '选', '奶', '打', '每', '评',
    '少', '算', '又', '因', '情', '找', '些', '份', '置', '适',
    '什', '蛋', '师', '气', '你', '姐', '棒', '试', '总', '定',
    '啊', '足', '级', '整', '带', '虾', '如', '态', '且', '尝',
    '主', '话', '强', '当', '更', '板', '知', '己', '无', '酸',
    '让', '入', '啦', '式', '笑', '赞', '片', '酱', '差', '像',
    '提', '队', '走', '嫩', '才', '刚', '午', '接', '重', '串',
    '回', '晚', '微', '周', '值', '费', '性', '桌', '拍', '跟',
    '块', '调', '糕']
    
font_data = dict(map(lambda x,y:[x,y],font1,font2))

现在文字和编码的一一对应关系就建立起来了!

最后就是将请求得到的源码,根据字典的键进行匹配,得到解密后的真实地址

font_list = [i for i in addr_text] #提取编码font_list = [str(i.encode('unicode_escape'))[-5:-1] if len(repr(i))>3 else i for i in font_list] #提取后四位

addr = ''.join([font_data.get(i) if len(i)>1 else i for i in font_list]) #匹配

addr = city + addr

代码很简单就不做过多讲解了,唯一需要注意的就是我们直接从网上请求返回的\uxxxx虽然是str格式,但是确实unicode编码,所以需要先使用repr进行转义后方可进行截断!

现在来测试一下

可以看到,该页所有地址信息全部被正确提取出来(关键信息已经打码)!

至此我们就成功破解大众点评网地址信息的字体加密,当然例如评分、均价等信息,我们可以如法炮制,只不过换了一个字体罢了,本文不在赘述!

搞定字体加密之后,我们就可以轻松的提取想要的信息,不过由于点评网的反爬机制,在爬取时务必要注意使用代理ip、控制频率等手段来防止被检测到!爬取的数据也切勿用于任何盈利及非法等用途!

(0)

相关推荐