python爬虫进阶-每日一学(图片反爬-雪碧图)

目的

了解熟悉雪碧图反爬策略

详细需求

在这里插入图片描述

url:http://glidedsky.com/level/crawler-sprite-image-1

思路解析一(错误)

一、审查
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
二、分析
通过观察雪碧图,发现数字有大有小,那么是否有不一样的逻辑呢
小数字处理
在这里插入图片描述
大数字处理

首先,我们知道css限定了宽高,
通过观察,发现高相同为15px,
那么如何才能表现为大呢,
那么只有宽数值越大,字体显示越大

在这里插入图片描述
三、汇总

1.源网页请求
2.获取css链接
3.正则提取所有类及宽高位置信息
4.雪碧图的值是固定的为0-9,本地赋值就可以
5.雪碧图区别在大小数字不同,但是以分析的逻辑进行处理可以映射为正确的数值
if 高-宽>1:
	小数字处理逻辑
else:
	大数字处理逻辑

思路解析二(错误)

上面的思路一,在实际操作中发现存在特殊情况,映射错误,那么就有了思路二

一、审查

参考思路一:审查

二、分析

已知情况分析:
1.雪碧图固定数字:0123456789
2.css中的类映射数字
3.pox值表示位置

在这里插入图片描述

由此,有一个猜想,多个css类映射同一pox值,pox值与雪碧图数字一一映射
那么,只需要构建好pox值与雪碧图一一映射关系就好

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

发现规律,随之数字的增大,pox值也随之增大(负的)
猜想,获取所有的pox值,进行排序,那么pox值下标则一一映射为数字

正则提取,进行去重,及排序后如图所示
在这里插入图片描述

经过验证,发现是可行的,实现pox值与数字的一一映射,多个页面检测均无误
这里是正常的理想情况:
获取pox值列表,有10个元素,分别对应0-9十个数字
映射思路:
1.获取一个去重,排序,元素数量为10的列表,如上图所示
2.查询pox值在列表的下标
3.下标的值即为映射的值
猜想,另一种情况,
页面中只用7个数字进行拼接,那么只能获取7个pox值,
那么这个时候,通过pox值下标映射数字的方法就不可用了,中间有断档

在这里插入图片描述

无法获取7的pox值,
那么利用列表查找pox元素获取index,index值就是pox映射值的思路就会映射错误

在这里插入图片描述

列表元素9个,丢失1个
如果按照以往的思路进行映射
1.查找-104pox值下标
2.-104的下标为7,即映射为7
但实际上在前面缺失一个值,即7的pox值
结果造成-104映射8变成7
解决:7的pox值在数字映射中没有出现,也代表没什么用,可以为任意值,
需要作的就是添加一个pox,用于占位,占住index为7的地方,那么就可以构成一一映射
那么解决思路如下:
1.通过规律观察,列表前一个-后一个的数值<15,则表示正常连续,无中断
2.列表前一个-后一个数值>15,则表示中断,
3.那么就在此处添加占位pox值,pox值为前一值-15
那么可以了,又可以实现一一映射

在这里插入图片描述
三、汇总

1.请求源网页
2.正则提取所有pox值
3.pox值去重排序列表
4.pox列表中断检测及处理
5.提取所有css类
6.实现:类-pox-index的映射

思路解析三

首先,分析思路解析二错误原因
原因:木有策略较好的构建映射
举例说明
图片平均宽	postion值1 postion值2 间隔距离  实际缺失值个数
11			46		   75        29       1
12          49         84        35       2
12          76         96        20       1
最后发现,没有较好的策略能够满足实际需求,会导致构建映射错误

一、审查

参考思路一

二、分析

参考思路二

三、图片的解码与保存
在这里插入图片描述

    def base64_image(self):
        '图片的解密与保存'
        base_png = re.findall(';base64,(.*?)"', self.html, re.S)[0]
        b = base64.b64decode(base_png)  # base64解密,保存为本地图片
        with open('59.png', 'wb') as f:
            f.write(b)

        img = cv2.imread("59.png")
        w = img.shape  # 图片的属性
        self.height = w[0]  # 高度
        self.width = w[1]  # 宽度

四、图片切割

依据中断处的postion值,进行图片切割,即传入的cutwidth值

    def pngcut(self,cutwidth):
        '图片切割'
        img = cv2.imread("59.png")
        # 要被切割的开始的像素的高度值
        beH = 0
        # 要被切割的结束的像素的高度值
        hEnd = self.height
        # 要被切割的开始的像素的宽度值
        beW = cutwidth
        # 要被切割的结束的像素的宽度值
        wLen = self.width
        # 对图片进行切割
        dstImg = img[beH:hEnd, beW:wLen]
        cv.imwrite("60.png", dstImg)

在这里插入图片描述

五、OCR识别

这里使用的百度AI开发者平台提供的文字识别API,大家可自行百度

    def baidu_api(self):
        """定义常量"""
        # time.sleep()
        time.sleep(2)

        APP_ID = '22847322'
        API_KEY = 'xxxxxxxxx'
        SECRET_KEY = 'xxxxxxx'

        """初始化对象"""
        client = AipOcr(APP_ID, API_KEY, SECRET_KEY)

        """读取图片"""

        from os import path

        # 保存在本地的图片路径
        images = path.join(path.dirname(path.abspath(__file__)), '60.png')
        image = self.get_file_content(images)

        """调用通用文字识别接口, 识别本地图像"""
        try:
            # result = client.webImage(image)   #网络图片识别
            result = client.basicGeneral(image) #通用文字识别
            # result = client.numbers(image)    #数字识别
            print(result)
            mum_list = result['words_result'][0]['words']
            return int(mum_list[0])
        except Exception as e:
            print(e)
            if 'Open api qps request limit reached' in str(e):
                return self.baidu_api()

在这里插入图片描述
六、汇总

1.请求源网页
2.正则提取源网页中图片字符并进行解码与保存本地
3.正则提取所有pox值
4.pox值去重排序列表
4.pox列表中断检测及处理(使用OCR)
5.构建postion-值的字典
6.提取所有css类
7.实现:类-postion-值的映射
8.累加计数

在这里插入图片描述

七、验证
在这里插入图片描述

八、源码

应网站维护者要求,可提供思路,部分关键代码,禁止源码
相关推荐
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页