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

it2024-07-05  39

目的

了解熟悉雪碧图反爬策略

详细需求

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.累加计数

七、验证

八、源码

应网站维护者要求,可提供思路,部分关键代码,禁止源码
最新回复(0)