某网站防爬虫/防盗资源的实现和破防

逛某漫画站,有想弄个爬虫把图片爬下来的想法。

但发现该站的原图是被做了切割的。如果找图片链接,直接下载,是这个样子的:

眼好花是不?而实质上网站显示的图片是这个样子:

挺有意思的,估计该网站这样设计,是防爬虫或者防盗其资源吧。

可以知道其切割逻辑:

如果直接下载图片,图片就是右图那个鸟样。

通过开发者工具看看元素,发现该img 的style="visibility: hidden;",下面多了一个画布 canvas,如下:

大概可以知道该网站的思路了:网站预先把图片切割好,生成倒叙切片图片(切多少片不固定),前端通过脚本加载图片后,再把图片切片,用正确的顺序把片段draw 到画布上。

模拟该网站的实现

为什么要模拟它?没有为什么,就是写着玩玩。

直接上一个html 代码,为了简便,直接把js也写里面了。

大概就是这样:

xml 复制代码
<!DOCTYPE html>
<head>
    <title>拆分图片</title>
</head>
<body>
    <div id="container">
        <img src="./00001.webp" id="album_photo_00001" style="visibility: hidden;">
    </div>
</body>

<script>
    // 实质使用上会单独到另一个文件(并且混淆),这里演示方便,扔这了。    
    function draw_image(canvas, image) {
        var count = 8; // 实际上 count 是根据某些规则,这里演示,直接写死

        var image_w = image.width;
        var image_h = image.height;
        var frame_h = image.height/count;

        // 倒叙摆放,把它转回来
        for (var i = 0; i < count; i++) {
            var start_h = frame_h * (count - i -1);
            context.drawImage(image, 0, start_h, image_w, frame_h, 0, frame_h * i, image_w, frame_h);
        }
    }

    window.onload = function() {
        // 加载图片
        var image = new Image();
        image.src = document.getElementById("album_photo_00001").src;

        // 创建画布
        var canvas = document.createElement("canvas");
        canvas.setAttribute('width', image.width);
        canvas.setAttribute('height', image.height);

        context = canvas.getContext("2d") ;

        draw_image(canvas, image);

        var container = document.getElementById("container");
        container.appendChild(canvas);
    }
</script>
</html>

运行效果:

图片的破防的思路

demo可以固定切片数,但爬虫应该如何知道切片数?

分析该网站js代码,会发现有个函数计算它(根据"漫画id 和图片id"来计算),虽然这段代码被混淆了,但有前端分析功底的伙伴这个不是难事。

本文说说求得切片数的另一个思路。

由于图片是被均匀的横向切割再拼接的,所以图片会有明显的横行线条,这不,就可以用openCV 对其进行横向线条获取和分析了?!

步骤就是用 Canny 检测边缘,之后通过HoughLinesP 检测线条,过滤非水平线即可。

ini 复制代码
img = cv.imread("00001.webp")
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray,50,150,apertureSize = 3)

for line in cv.HoughLinesP(edges, 1, np.pi / 180, 100, minLineLength=10, maxLineGap=1000):
    x1,y1,x2,y2 = line[0]
    angle = np.degrees(np.arctan2(y2 - y1, x2 - x1))
    if abs(angle) > 1:
        continue

    cv.line(img, (x1,y1), (x2,y2), (0,255,0), 2)

如下,openCV 识别横向线条(画出绿色线标注)效果:

有了这些线条,便可对它们进行聚合整理(再做些基本的校验),不难得出切割的图片数多少。

识别出线条数,便可知道切片多少了(如上图,线条整合就是七束,也就是八块)。后面几乎就等价于用python 把上面js 写一遍,再保存新图片即可。

还原图片代码:

ini 复制代码
import cv2 as cv
import numpy as np

img = cv.imread("00001.webp")

emptyImage = np.zeros(img.shape, np.uint8)

# 根据识别结果填充,测试所以写定了。
count = 8

image_h, image_w, frame_h = img.shape[0], img.shape[1], int(img.shape[0] / count)

for i in range(count):
    img_offset_y = i * frame_h
    result_offset_y = (count - 1 - i) * frame_h

    # 倒叙还原过来
    for y in range(frame_h):
        for x in range(image_w):
            emptyImage[img_offset_y + y, x] = img[result_offset_y + y, x]

cv.imwrite("result.png", emptyImage)

完整的爬站代码就不上了,本文主要是说说思路,有编程功底的看官,稍微整理下,整合一个防破的爬虫代码不是啥难事。

相关推荐
ai小鬼头1 小时前
Ollama+OpenWeb最新版0.42+0.3.35一键安装教程,轻松搞定AI模型部署
后端·架构·github
萧曵 丶2 小时前
Rust 所有权系统:深入浅出指南
开发语言·后端·rust
老任与码2 小时前
Spring AI Alibaba(1)——基本使用
java·人工智能·后端·springaialibaba
蹦蹦跳跳真可爱5893 小时前
Python----OpenCV(图像増强——高通滤波(索贝尔算子、沙尔算子、拉普拉斯算子),图像浮雕与特效处理)
人工智能·python·opencv·计算机视觉
nananaij3 小时前
【Python进阶篇 面向对象程序设计(3) 继承】
开发语言·python·神经网络·pycharm
雷羿 LexChien3 小时前
从 Prompt 管理到人格稳定:探索 Cursor AI 编辑器如何赋能 Prompt 工程与人格风格设计(上)
人工智能·python·llm·编辑器·prompt
华子w9089258593 小时前
基于 SpringBoot+VueJS 的农产品研究报告管理系统设计与实现
vue.js·spring boot·后端
星辰离彬3 小时前
Java 与 MySQL 性能优化:Java应用中MySQL慢SQL诊断与优化实战
java·后端·sql·mysql·性能优化
敲键盘的小夜猫4 小时前
LLM复杂记忆存储-多会话隔离案例实战
人工智能·python·langchain
高压锅_12204 小时前
Django Channels WebSocket实时通信实战:从聊天功能到消息推送
python·websocket·django