将html转图片-实现网页截图与ui对比实践方案如何将html代码转成图片? 场景类似cssbattle这样,在线体验
在线体验
- cssbattle.wuwenzhou.com.cn/index 来试一试,真的勇士看自己能下多少层!!!
需求分析
- 将html代码转成图片。
- 场景类似cssbattle这样对比代码,ui检测,或者在线生成pdf,png这样的图表,书籍等等
常见解决方案科学上网
前端方案
- git地址: html2canvas实现原理 使用dom在canvas中渲染,再使用canvas转图片,然后在保存成base64的实践
- 优势:实践起来很简单。
- 劣势:css3支持度不好,截图应对不同场景需要计算宽高,上传数据交互之间也相对麻烦,接口数据可以被修改,应该上传的本身已经是图片而不是代码了后面的逻辑就不能得到很好的保证。
后端方案
- git地址:wkhtmltopdf 这样c++方案
- 优势:使用方便有python这样包可以封装调用,截图效果好无需其他转换
- 劣势:在docker安装比较麻烦,css3支持力度比较差
其他方案
- 谷歌插件或者付费网站等等
- 优势:使用方便
- 劣势:业务结合复杂度高,只能在特定场景下面使用,付费那绝对是不可能的
原生方式
- chorme,使用本身能力截图
- 优势:还原度最高
- 劣势:安装复杂,截图颜色值需要转换
技术选型
- 综合考虑还是使用原生能力,还原度是第一述求
代码实现
pyton代码
- 封装截图能力 git地址:html2image
from html2image import Html2Image
def screenshot(data):
# 使用SRGB颜色模式兼容对比ps中导出的图片格式
hti = Html2Image(custom_flags=['--force-color-profile=SRGB','--disable-gpu'])
# 解析请求数据
data = request_parse(request)
htmlCode = data['code']
# 生成随机图片地址
timestamp = int(time.time())
randomStr = ''.join(random.sample('zyxwvutsrqponmlkjihgfedcba',5))
png = str(timestamp)+ randomStr + ".png"
# 在docker的headless类型的chorme没有高度 这个是个不友好的方式
htmlTmp= """
<html style="height:100%;">
<head>
</head>
<body style="height:100%;">
{content}
</body>
</html>
"""
htmlTmp = htmlTmp.format(content=htmlCode)
#截图完成,其他api可以再git中查看
hti.screenshot(html_str=htmlTmp,save_as=png,size=(400, 300))
- 图片对比 图片操作:opencv,数据对比:numpy
- ps: 为什么不用常见的图片比较方法类型:均值、差值、感知哈希算法,三直方图算法和单通道等等算法,因为当前的场景是比较两个图片是否一致而不是相似度的比较,不需要相似值,而是决定误差是多少
def runIMGCompareFun(para1, para2):
img1 = cv2.imread(para1)
img1 = cv2.resize(img1, (400, 300))
img2 = cv2.imread(para2)
img2 = cv2.resize(img2, (400, 300))
#使用矩阵相比求均值的方式计算绝对误差值
arr = img1 == img2
scale = np.average(arr)
return scale
构建依赖
pipreqs --encoding=utf-8 --force
docker容器化
# 基于镜像基础
FROM python:3.7
# 端口
EXPOSE 9567
# 设置代码文件夹工作目录 /app
WORKDIR /app
# 复制当前代码文件到容器中 /app
COPY . /app
# 时间设置很重要
RUN echo "Acquire::Check-Valid-Until \"false\";\nAcquire::Check-Date \"false\";" | cat > /etc/apt/apt.conf.d/10no--check-valid-until
# 镜像源设置
RUN sed -i 's|security.debian.org/debian-security|mirrors.ustc.edu.cn/debian-security|g' /etc/apt/sources.list
RUN sed -i 's#http://deb.debian.org#https://mirrors.163.com#g' /etc/apt/sources.list
# 下载依赖
RUN apt-get clean
RUN apt-get update -y && apt-get install -y icc-profiles-free
RUN apt-get update -y && apt-get install -y chromium
# 无头浏览器设置很重要
RUN echo 'export CHROMIUM_FLAGS="$CHROMIUM_FLAGS --no-sandbox --disable-gpu"' >> /etc/chromium.d/default-flags
# MOTD
RUN echo " \n =============HTML2IMAGE============= \n Welcome to the html2image CLI container ! \n Type html2image -h for help :)" >> /etc/motd
RUN echo "clear" >> /root/.bashrc
RUN echo "cat /etc/motd" >> /root/.bashrc
# 设置python静态
RUN pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
# 安装所需的包
RUN pip install -r requirements.txt
# Run app.py when the container launches
CMD ["python", "run.py"]
总结
-
为什么是python?图片处理和ai后续扩展是选型pyhon最重要的原因,场景性和长久性的选择。
-
python部署实在很麻烦,环境依赖项比较多。
-
本地开发和docker容器内部的一致性很重要,本地代码是好的,进入容器内代码就不能正常运转,这次开发的最大感悟。
-
容器化部署和升级这次确实给我带来极大的便捷,脚本写好流程,构建docker,发布docker,远程使用docker-watchtower监听容器变化更新重启确实很爽。
-
祖国母亲生日快乐,大家节日快乐!!!
转载自:https://juejin.cn/post/7013944873631875103