前言
记得好早之前,我做过关于外卖平台字体加密反爬的总结笔记,今天给大家记录另外一种常见的反爬 —— SVG 映射
什么是SVG呢?
SVG 全称为 Scalable Vector Graphics,是一种基于 XML 并可以缩放的矢量图片文件格式
而 SVG 反爬是利用 CSS 样式及 SVG 图片,将 SVG 图片中提取字符内容,映射到网页元素中,由于不能直接通过网页元素直接提取数据,所以起到了反爬的目的。
解决思路和流程
1、分析
打开我们碰到的目标页面,查看页面中电话号码的网页元素
我们发现,电话号码中的每一个数字都对应一个 d 标签,d 标签中的 class 属性值都是以「 vhk 」开头的
![在这里插入图片描述](https://img-blog.csdnimg.cn/abebb74ab70548df9936c5ea75892d75.png)
查看右侧 Styles 样式标签后,发现上面匹配的 d 标签的背景图片「 background-image 」被设置为一张 SVG 图片,d 标签的宽度固定为 14px,高度为 30px
在样式「 vhkbvu 」中,通过定义 background_position 指定背景图片的移动方向,比如:图中相当于背景图片向左移动 386px,向上移动 97px
![在这里插入图片描述](https://img-blog.csdnimg.cn/c72824c2ad0f426abc4a5d9fa47cab03.png)
然后,我们查看 svg 图片的源文件
- 字体大小为 14px,颜色值为 #666
- 4 个 text 标签代表 4 行数字
- 4 行数字对应的 y 轴坐标值固定为 38、83、120、164
![在这里插入图片描述](https://img-blog.csdnimg.cn/c64c8635ce81447bad281efdd2a5ec0d.png)
因此,我们能得出一个结论,即:d 标签通过 SVG 背景图片,结合一定的偏移量 + 宽高度,从 SVG 图片中固定一个数字展示在页面上
2、实现
首先,我们获取 SVG 图片、CSS 样式文件的源文件
PS:为了方便后面样式的解析,需要将 CSS 样式源码的换行符和空格全部删除掉
import requests
...
def start(self):
self.svg_source = requests.get("http://www.porters.vip/confusion/font/food.svg").text
self.css_source = requests.get("http://www.porters.vip/confusion/css/food.css").text.replace('\n', '').replace(
' ', '')
...
然后,使用正则表达式解析 SVG 图片源文件,提取所有的 y 轴坐标及行数据列表
import re
...
def parse_svg(self):
"""
解析svg文件
:return:
"""
text_content = re.findall('y="(.*?)">(.*?)</text>', self.svg_source, re.S)
return [item[0] for item in text_content], [item[1] for item in text_content]
...
数据格式如下:
['38', '83', '120', '164']
['154669136497975167479825383996313925720573', '560862462805204755437571121437458524985017', '671260781104096663000892328440489239185923', '684431081139502796807382']
最后,遍历要解析的样式名,从 SVG 图片中提取对应的数值
需要注意的是,SVG 图片的文字大小固定为 14px,根据行内容提取值时,只需要利用偏移量获取索引值,最后拿到实际指向的数值即可
...
def get_number_from_svg(self, style_name, y_nums, datas):
"""
获取svg中实际的数据
:param y_nums: y轴坐标列表
:param datas: 数据值列表
:return:
"""
deviation_x, deviation_y = \
re.compile('.%s{background:-(\d+)px-(\d+)px;}' % style_name).findall(self.css_source)[0]
position_y = [y for y in y_nums if int(deviation_y) <= int(y)][0]
content = datas[y_nums.index(position_y)]
x_index = int(int(deviation_x) / 14)
return str(content[x_index])
...
以上就完成了对页面中「 电话号码 」的解析,我们只需要提取页面元素中的样式名,获取映射的数值进行替换即可
扩展:
CSS 偏移反爬:https://blog.csdn.net/JavaShark/article/details/125135513
字体加密:https://blog.csdn.net/weixin_42277380/article/details/99288286?spm=1001.2014.3001.5501
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)