python爬虫入门 ✦ 大众点评网字体反爬

此博客仅为我业余记录文章所用,发布到此,仅供网友阅读参考,如有侵权,请通知我,我会删掉。

1.问题解析

1.1 进入主题,输入网址。打开开发者工具后可以看到,我们想要获取的人均价格信息是一片空白。
别急,这是网站做了字体反爬。那有字体反爬,我们就得先去找到做了字体反爬的字体,这个时候往往会有字体链接。
看一下右边的font-family,该字体文件名为PingFangSC-Regular-shopNum,现在点击一下我画框的地方。(字体链接)在这里插入图片描述
1.2 点击界面跳转后,好家伙,这里居然不止一个字体文件。难道说网站做了不止一个字体反爬??
在这里插入图片描述
1.3 再回到页面看看,发现菜馆类型的是font-family: PingFangSC-Regular-tagName;
地址的又是font-family: PingFangSC-Regular-address;。现在,我们知道哪些字体对应哪些文件了之后,下面就是解决问题的时候了。
在这里插入图片描述
在这里插入图片描述
1.4 鼠标放到这个箭头指向的地方,会弹出一个画框所示的链接,记住这个链接,高考要考!!!
在这里插入图片描述

2.问题解决

2.1 先将上面找到的字体链接下载下来,然后到百度字体编辑器http://fontstore.baidu.com/static/editor/index.html,将下载好的字体文件在该网址打开,看到如下图
发现每一个字体都有一个对应的uni码,足足有7页共601字体。好家伙,这么多个字体,怕是要搞到秃头
在这里插入图片描述
2.2 现在我们看一下这家商铺的人均价格,然后去看一下源代码与百度字体编辑器打开的字体文件。
看到没!!!
在这里插入图片描述
通过分析可以发现,字体文件的uni码后四位网页源代码的反爬字体的后四位 是完全对应的!这就是解决问题的关键!!!
在这里插入图片描述
2.3 那,接下来就是上代码了。

3.核心代码 + 思路

我解决该问题的方法是
1.下载字体文件
2.将字体文件转换成xml文件
3.分析xml
4.设置基准字典
5.遍历基准字典获取与最新字体匹配的正确文字

3.1 下载字体文件
还记得上面我说的高考要考的链接不,没错,他就是页面所需要的字体反爬的字体文件.woff
在网页源代码搜索plus就可以看到下面这种url

href="//s3plus.meituan.net/v1/mss_0a06a471f9514fc79c981b5466f56b91/svgtextcss/9354159d084b2d4de011be813dbb83e0.css"

请求后的他是这个样子的。接下来就是在这里获取所有的woff文件,因为你要破解字体反爬嘛。
在这里插入图片描述
先请求获取上图的源代码,然后用以下代码下载所有所有的字体文件。

woff_urls = re.findall(r'url\("//(.*?)"\)', svgtext.text)
for woff_url in woff_urls:
	if '.woff' in woff_url:
		# 遍历所有的woff文件出来
		woff_url = 'http://' + woff_url
		# 字体的名称取最后面的,因为太长了
		woff_name = woff_url.split('/')[-1]
		# 如果字体文件不存在本地,则创建
		if not os.path.exists(woff_name):
			with open(woff_name, 'wb') as f:
				f.write(woff_content)
				print(woff_name + '下载成功')

3.2 字体文件转换成xml

# 导入解析字体的模块
from fontTools.ttLib import TTFont

font = TTFont('xxx.woff')	# 这里放入字体文件
font.saveXML('xxx.xml')		# 这里为字体文件转换成xml的名称

3.3.1 分析xml
转换成xml文件之后,我们打开xml来看看。可以看到对应 的字体文件有一大堆x,y数据,估摸着这是个图形吧,话不多说,下面画图一波。
在这里插入图片描述
3.3.2 xml画图
看到画出来的就是一个。。。是不是很神奇呢!下面上画图的代码。
在这里插入图片描述

# 画图代码
import matplotlib.pyplot as plt
import re
str = '''此处放入xml的字体文件数据'''

x = [int(i) for i in re.findall(r'<pt .*?x="(.*?)"', str)]
y = [int(i) for i in re.findall(r'y="(.*?)" x=', str)]

print(x)
print(y)

plt.plot(x, y)
plt.show()

3.3.3 对比不同的xml文件
这里博主比对了多个字体转换成的xml文件,发现他们uni码不一样,但是他们对应的其他参数都一样。等等??这就是我们本次案例的思路!!没错,因为每一个字体的信息都一样,所以我们的思路是先做一个基准用来做比对的字典文件{ unicode: 汉字}。
在这里插入图片描述
3.4 设置基准字典

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

# 这里不做详细介绍为何如此操作,可以自己去补一下这方面的知识            
base_font = TTFont('xxx.woff')  # 打开本地字体文件
base_obj_list = base_font.getGlyphNames()[1:-1]  # 获取所有字符的对象,去除第一和最后
base_uni_list = base_font.getGlyphOrder()[2:]  # 获取所有编码,去除前2个  
# 这样可以获取到我们需要基准字典了。       
base_dict = {}
for k, v in zip(base_uni_list,  basefont_char):
	base_dict[k] = v

3.5 遍历基准字典获取与最新字体匹配的正确文字
下面代码展示新字体文件与基准字体字典的对比,并生成新的字体字典。

base_dict = {}
new_font = TTFont(new.woff)	# 打开新字体
obj_list2 = new_font.getGlyphNames()[1:-1]
uni_list2 = new_font.getGlyphOrder()[2:]

for uni1 in base_uni_list:
	obj1 = base_font['glyf'][uni1]
	
	for uni2 in uni_list2:
		obj2 = new_font['glyf'][uni2]
		# 将与基准字典对比后的 unicode 和 汉字 添加到base_dict
		if obj1 == obj2:
			self.get_tag[uni2] = base_dict[uni1]
			

3.6 效果图
在这里插入图片描述

4.后话

如果完成上面的代码后,这个案例已经完成99%了。剩下的就是替换汉字与网页源代码的替换和数据提取了,这些就不上代码了。

至此,本项目案例分享结束。主要是分享思路。
不上完整代码,是因为纸上得来终觉浅,还是得动手操作一番。
如果需要完整项目案例代码可以留下你的邮箱,我发送给你。
因个人能力不足,难免有错误之处,所以恳请各位指正。。

发布了34 篇原创文章 · 获赞 210 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_45081575/article/details/100337497