爬虫-滑动图片缺口识别,及滑动行为数据伪造

前言

由于最近爬虫项目遇到行为效验,导致项目下游相关业务版块进入暂停运营阶段,于是我就大致分析了下解决大致方案。

好在之前有过处理类似的业务项目,然后我又在网上找了一些相关的资料,嘿嘿嘿~

你们是遇到对手了~

涉及编程语言:PHP、JavaScript

大致处理思路:通过二值化图像,找出横向图像中,纵列区间段占颜色均值最高的缺口图片。

此文干货较长,若与笔者见解不一致,欢迎随时留言。


关于图片的处理

首先分析出目标站点接口返回的数据,在给出的所有行为效验数据中。笔者通过分析,服务端回给客户端的行为效验数据,只有:纵坐标位置,及效验的背景缺口底图和滑动图片。

而客户端只要对滑动图片和背景缺口底图进行拼合,再有客户端发起封包向服务端对做数据效验(滑动轨迹、滑动图片停止的横向位置、客户端会话、客户端ip)等。

如下是笔者对滑动图片的处理流程

1、载入 滑动背景底图

2、载入滑动拖动图片

3、加载图片信息(宽高)

通过PHP的GD图像处理库,对上述的两个图片信息的宽高进行获取,见下图

调用示列
相关代码
图片信息

4、标记纵坐标位置

至此“我们”在每次切入重心点先从“滑动图片”纵向位置为主要下手点。

缺口位置纵向高度

5、分割滑动背景底图图片

以横向起点0,到背景缺口底图的最大宽度为终点。截取出“主要的分析图片”的,以纵向位置为起点向“滑动图片”的高度区域为终点做出图片截取,见下图所示。

提取主要图片内容

6、灰度分割后的图片

灰度数字图像是每个像素只有一个采样颜色的图像。这类图像通常显示为从最暗黑色到最亮的白色的灰度,尽管理论上这个采样可以任何颜色的不同深浅,甚至可以是不同亮度上的不同颜色。灰度图像与黑白图像不同,在计算机图像领域中黑白图像只有黑白两种颜色,灰度图像在黑色与白色之间还有许多级的颜色深度。

灰度后台的图片

php图片转灰度算法

    /**
     * 设置->图片灰度
     *
     * @param mixed $ResourceImage 资源图片
     *
     * @return resource
     */
    protected final function setGray($ResourceImage) {
        $img_width  = ImageSX($ResourceImage);
        $img_height = ImageSY($ResourceImage);
        for ($y = 0; $y < $img_height; $y++) {
            for ($x = 0; $x < $img_width; $x++) {
                $gray = ( imagecolorat($ResourceImage, $x, $y) >> 8 ) & 0xFF;
                imagesetpixel($ResourceImage, $x, $y, imagecolorallocate($ResourceImage, $gray, $gray, $gray));
            }
        }
        return $ResourceImage;
    }

7、二值化图片

图像二值化( Image Binarization)就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程。调整对应“阈值”数值。让图像上的块色域更能明显突出。

php图片转二值化算法

   /**
     * 获取指定位置颜色值
     *
     * @param mixed $ResourceImage 图片资源
     * @param int   $X             横向坐标
     * @param int   $Y             纵向坐标
     *
     * @return array
     */
    protected final function getPicturePositionRgbColor($ResourceImage, int $X, int $Y) {
        $rgb = imagecolorat($ResourceImage, $X, $Y);
        $r   = ( $rgb >> 16 ) & 0xFF;
        $g   = ( $rgb >> 8 ) & 0xFF;
        $b   = $rgb & 0xFF;
        return [$r, $g, $b];
    }

    /**
     * 设置->图片二值化
     *
     * @param mixed $ResourceImage 图片资源
     * @param int   $Threshold     阈值
     */
    protected final function setImageBinarization($ResourceImage, int $Threshold) {
        //图片->宽度
        $image_width = imagesx($ResourceImage);
        //图片->高度
        $image_height = imagesx($ResourceImage);
        //遍历横向区域
        for ($i = 1; $i <= $image_width; $i++) {
            //遍历纵向区域
            for ($j = 1; $j <= $image_height; $j++) {
                //取出图片颜色
                [$r, $g, $b] = $this->getPicturePositionRgbColor($ResourceImage, $i, $j);
                //三色求平均值
                $avg = ( $r + $g + $b ) / 3;
                //对像素点设置指定颜色
                imagesetpixel($ResourceImage, $i, $j, $avg >= $Threshold ? imagecolorallocate($ResourceImage, 255, 255, 255) : 0);
            }
        }
    }

关于图片的数据分析

按上述流程执行完后,在对底图横向每一格的像素纵列求出列“颜色均值”,并把对应的数据以可观的分析图展示出来。

二值化后的分析图

从上述图中可以看到醒目的红色标记块,从这个过程,我们就可以找出适应的“阈值”,来让处理的二值化图片更醒目,也能让后续算法的工作量更少,从而达到识别出横向位置所在具体区域。

PHP求出图片横向每一格纵列“RGB颜色均值”算法


    /**
     * 获取->求出图片横向每一格纵列“RGB颜色均值”算法
     *
     * @param mixed $ResourceImage 图片资源
     *
     * @return array
     */
    protected final function getImageHorizontalPxRgbArray($ResourceImage): array {
        //图片->宽度
        $image_width = imagesx($ResourceImage);
        //图片->高度
        $image_height = imagesx($ResourceImage);


        $horizontalArray = [];
        //遍历横向区域
        for ($i = 1; $i <= $image_width; $i++) {
            //累计值
            $sum = 0;
            //遍历纵向区域
            for ($j = 1; $j <= $image_height; $j++) {
                //取出图片颜色
                [$r, $g, $b] = $this->getPicturePositionRgbColor($ResourceImage, $i, $j);
                //三色求平均值
                $avg = ( $r + $g + $b ) / 3;
                //累加均值
                $sum += $avg;
            }
            //该纵向列的总和在除以图片的高度,即得出纵列“RGB颜色均值”
            $horizontalArray[] = $sum / $image_height;
        }
        return $horizontalArray;
    }

如何通过算法,获取横向坐标缺口位置?

横向每一格纵列“RGB颜色均值”求出来后,经过笔者分析,切入重点可以放在每次横向每一格像素点往右移动“滑动图片宽度距离”,并在此移动过程中,计算并记录出区域的总值,并把最后的答案设为answerPosition,大致思路如下图。

PHP算法

   /**
     * 获取->答案位置
     *
     * @param array $VerticalArrayData 纵向数组数据
     * @param int   $SlideImageWidth   滑动图片宽度
     *
     * @return int
     */
    protected final function getAnswerPosition(array $VerticalArrayData, int $SlideImageWidth): int {
        //
        $answerArr = [];
        //纵向长度
        $vertical_len = count($VerticalArrayData);
        //遍历横向
        for ($i = 1; $i <= $vertical_len; $i++) {
            $sum = 0;
            //计算区域宽度
            $calc_area_width = $i + $SlideImageWidth;
            //判断当前计算区域宽度是否大于总长度
            if ($calc_area_width > $vertical_len) {
                //取出可计算的宽度
                $tempWidth = $vertical_len - $i;
            } else {
                //赋值可计算的区域宽度
                $tempWidth = $SlideImageWidth;
            }
            if ($tempWidth <= 0) continue;
            //遍历滑动图片区域颜色均总值
            for ($j = 1; $j <= $tempWidth; $j++) {
                //累加该区域颜色均值
                $sum += $VerticalArrayData[$i + $j] ?? 0;
            }
            //记录位置
            $answerArr[] = [
                'x' => $i,
                'v' => $sum,
            ];
        }
        //找出颜色最大范围横向位置(找大小)
        $ansIndex = $ansXValue = 0;
        foreach ($answerArr as $k => $v) {
            if ($ansXValue <= $v['v']) {
                $ansIndex  = $k;
                $ansXValue = $v['v'];
            }
        }
        //返回答案所在横向坐标
        return $ansXValue[$ansIndex]['x'];
    }

关于真人滑动的数据分析

在浏览器客户端进行行为效验滑动操作过程中,经过分析,用户每一次向左或者向右滑动数组数据结构体大致如下:

从前文概述中,我们已经知道“纵向坐标位置”是已知参数,而“横向坐标位置”是需要通过一定的技术算法获取出答案位置,所停留的时间,这块则是需要当前时间加上随机数字做累加处理。至此为大概求解思路分析完毕。

通过技术手段抓取的真实滑动轨迹数据分析折线图,笔者依次按快、中、慢做如下截图展示:

从上述三个折线分析图中,依次能看出部分滑动轨迹数据的变化,而每次滑动的范围长度是不定的,这里我们设为随机N。

X坐标则是处于一个缓慢上升的阶段,中间部分有一小段数据快速增高,后继部分续保持平匀速增加。那么这里生成的X坐标数据思路,笔者这里的构思算法是

startX=rand(200,230);

endX=startX+answerPosition+rand(10,20);

Y坐标非常明显,几乎处于平衡线,但是细看数据,有一小部分数据还是有变动的,那么我们既可以对该参数值设定一个初始值,然后每次生成数据做随机小范围的累加或者累减,笔者这里设定是-2到3。

timeStamp在快和中的滑动分析图中,可以明显看出增长弧度非常平缓,而慢滑动则是梯阶速度增加。笔者这里选择参考范围值,是慢滑动生成数据,即随机范围值在3到20的每次累加。

如何让算法伪造滑动数据

通过前面的讲解思路,我们已知:N、startX、endX、Y和timeStamp的随机范围值;最后通过率较高灵魂滑动算法生成的图如下:

伪造滑动轨迹分析图

PHP算法

   /**
     * 创建滑动原始数据
     *
     * @param int $EndPosition 结束位置
     *
     * @return array
     */
    public final function createSlideRawData(int $AnswerPosition): array {
        //移动轨迹记录
        $track = [];
        //当前横向位移初始位置
        $currentX = rand(200, 230);
        //当前纵向位移初始位置
        $currentY = rand(190, 200);
        //当前起始停留时间
        $timeStamp = rand(5, 15) * 100;
        //结束位置
        $EndPosition = $currentX + $AnswerPosition+ rand(10, 20);
        //减速阈值
        $mid = $EndPosition * ( 4 / 5 );
        //计算间隔
        $t = 0.5;
        //初始速度
        $v = 0;
        while ($currentX < $EndPosition) {
            if ($currentX < $mid) {
                #加速度为2
                $a = rand(1, 3);
            } else {
                //加速度为-3
                $a = rand(-2, 0);
            }
            $v0 = $v;
            $v  = $v0 + $a * $t;
            //移动横坐标
            $move = $v0 * $t + 1 / 2 * $a * $t * $t;
            //当前位移
            $currentX += $move;

            $track[] = round($currentX);
            $track[] = $currentY += rand(-2, 3);
            $track[] = $timeStamp += mt_rand(3, 20);
        }
        return $track;
    }

感谢您的观看,文中部分思路来之网络及朋友的部分技术指导。本文技术攻略若是对你有帮助,各位老爷们那就安排 “ 打赏+分享 ” 把~

转载请标明原处,谢谢。

滑动图片识别爬虫
暂无评论

发送评论 编辑评论


				
上一篇
下一篇