【解决】常见反爬总结之SVG映射

前言

记得好早之前,我做过关于外卖平台字体加密反爬的总结笔记,今天给大家记录另外一种常见的反爬 —— SVG 映射

什么是SVG呢?
SVG 全称为 Scalable Vector Graphics,是一种基于 XML 并可以缩放的矢量图片文件格式
而 SVG 反爬是利用 CSS 样式及 SVG 图片,将 SVG 图片中提取字符内容,映射到网页元素中,由于不能直接通过网页元素直接提取数据,所以起到了反爬的目的。

解决思路和流程

1、分析
打开我们碰到的目标页面,查看页面中电话号码的网页元素
我们发现,电话号码中的每一个数字都对应一个 d 标签,d 标签中的 class 属性值都是以「 vhk 」开头的
在这里插入图片描述
查看右侧 Styles 样式标签后,发现上面匹配的 d 标签的背景图片「 background-image 」被设置为一张 SVG 图片,d 标签的宽度固定为 14px,高度为 30px

在样式「 vhkbvu 」中,通过定义 background_position 指定背景图片的移动方向,比如:图中相当于背景图片向左移动 386px,向上移动 97px
在这里插入图片描述

然后,我们查看 svg 图片的源文件

  • 字体大小为 14px,颜色值为 #666
  • 4 个 text 标签代表 4 行数字
  • 4 行数字对应的 y 轴坐标值固定为 38、83、120、164
    在这里插入图片描述
    因此,我们能得出一个结论,即:d 标签通过 SVG 背景图片,结合一定的偏移量 + 宽高度,从 SVG 图片中固定一个数字展示在页面上

2、实现

首先,我们获取 SVG 图片、CSS 样式文件的源文件
PS:为了方便后面样式的解析,需要将 CSS 样式源码的换行符和空格全部删除掉

import requests

...
def start(self):
        # 1、svg源文件
        self.svg_source = requests.get("http://www.porters.vip/confusion/font/food.svg").text

        # 2、css文件源文件
        # 注意:将换行符、空格清除,方便下一步匹配
        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:
        """
        # 获取y轴值及数据
        text_content = re.findall('y="(.*?)">(.*?)</text>', self.svg_source, re.S)

        # print(text_content)
        # y轴值及行数据
        return [item[0] for item in text_content], [item[1] for item in text_content]
...

数据格式如下:

# y轴值列表及行数据值如下
# y轴值列表
['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:
        """
        # 使用正则表达式从样式内容中匹配x轴、y轴的偏移量(去除了换行符、空格),匹配正数字,\d+
        deviation_x, deviation_y = \
            re.compile('.%s{background:-(\d+)px-(\d+)px;}' % style_name).findall(self.css_source)[0]

        # 获取svg图片中的y轴坐标
        # 注意:这里取首次大于偏移量的y轴坐标,作为截取数据真实的y轴坐标
        position_y = [y for y in y_nums if int(deviation_y) <= int(y)][0]

        # 获取y轴坐标的索引值,然后获取该行的内容
        content = datas[y_nums.index(position_y)]

        # svg字体大小为14px,因此可以通过【偏移量/字体大小】拿到x轴的索引
        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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值