前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Hexo -42- 服务器搭建网页自动截图服务

Hexo -42- 服务器搭建网页自动截图服务

作者头像
为为为什么
发布2023-03-10 16:05:56
7740
发布2023-03-10 16:05:56
举报
文章被收录于专栏:又见苍岚

之前实现了在 Ubuntu 服务器上网页自动截图的功能,本文记录将其部署在服务器上的过程。

实现思路

在实现 Ubuntu 自动截图的基础上,需要将该功能部署成前端可以访问的服务

  1. 配置好自动截图所需的服务
  2. 前端发送需要使用的网址列表
  3. 搭建后端程序,监听端口,启动线程异步执行截图功能并保存在某个文件夹
  4. 保存的文件名为网址的 md5 字符串
  5. 前端调用图像时在前端计算网址的 md5 值并拼凑出图像地址进行图像
  6. nginx 反向代理提供 https 链接
  7. 设置系统开机自动启动服务

实现步骤

web 截图环境配置
前端发送网址列表

通过 ejs 模板结合 js 脚本代码获取 yaml 配置文件 中的网址列表

代码语言:javascript
复制
<script>
	var total_links={};
	var index = 0;
	<% for(const sub_item of theme.vvd_local_links.families || []) { %>
		<% for(const link_info of sub_item.items || []) { %>
			total_links[index] = '<%- link_info.link %>'
			index = index+1;
		<% } %>
	<% } %>

</script>

使用 jquery 发送 post 请求

代码语言:javascript
复制
<script src="https://101.43.39.125/HexoFiles/js/vvd_js/jquery.js"> </script>
<script>
    var url = 'https://yourhost:port/make_post_img'
    $.post(url, total_links);
</script>

搭建后端
  • 后端用 Python 实现监听端口服务,开放某个端口和路由
  • 获取 request 后解析出网址列表
  • 参考代码:
代码语言:javascript
复制
from flask import Flask, request
from flask_cors import CORS
import mtutils as mt
from lib import FileManager


port = '3000'
log_file_path = 'log.log'
app = Flask(__name__)
app.logger = mt.log_init(log_file_path)
CORS(app, supports_credentials=True)
file_manager = FileManager(app.logger)


@app.route("/make_post_img", methods=['GET','POST'])
def make_post_img():

    url_dict = dict(request.values)
    url_list = list(url_dict.values())
    file_manager.infer_screenshots(url_list, 'screenshots')
    
    return 'make_post_img'



if __name__ == '__main__':
    app.logger("**************** FileManager Sever Start *******************")
    app.run('0.0.0.0', port=port)
    pass

  • 核心功能在 FileManager 类中实现
代码语言:javascript
复制
import time
import mtutils as mt
from selenium import webdriver
import hashlib
from threading import Thread, Lock


def async_call(fn):
    def wrapper(*args, **kwargs):
        Thread(target=fn, args=args, kwargs=kwargs).start()

    return wrapper


class FileManager:
    FileRoot = "~/FileManager/"
    lock = Lock()

    def __init__(self, logger):
        self.logger = logger
        mt.dir_check(self.FileRoot)
        self.fail_list = []

    @async_call
    def infer_screenshots(self, input_url_list, dir_name):
        print('Start infer_screenshots. ')
        target_dir = mt.OS_join(self.FileRoot, dir_name)
        mt.dir_check(target_dir)

        cur_img_list = mt.glob_recursively(target_dir, 'jpg')
        stem_list = mt.get_list_from_list(cur_img_list, lambda x: mt.get_path_stem(x))
        tar_list = []

        for input_url in input_url_list:
            md5_str = mt.md5(input_url)
            if md5_str not in stem_list:
                if input_url not in self.fail_list:
                    tar_list.append(input_url)
        try:
            self.screen_shot(tar_list, target_dir)
        except Exception as e:
            print(e)
        print('Finish infer_screenshots. ')


    def screen_shot(self, url_list, save_dir):
        time.sleep(2)
        options = webdriver.ChromeOptions()
        options.add_argument("--no-sandbox")
        driver = webdriver.Chrome(chrome_options=options)
        width = int(1024)
        height = int(768)
        driver.set_window_size(width, height)
        driver.set_page_load_timeout(10)

        for url in mt.tqdm(url_list):
            print(url)
            try:
                driver.get(url)
                md5_str = mt.md5(url)
                self.logger(driver.title)
                img_path = mt.OS_join(save_dir, md5_str+'.jpg')
                time.sleep(5)  # 延迟截图
                driver.get_screenshot_as_file(img_path)  # 保存截图
            except Exception as e:
                self.fail_list.append(url)
                self.logger(e)

        driver.close()  # 关闭浏览器
        driver.quit()

  • 主要逻辑为获取 url 列表,挑出本地没有存到的图像,开启 异步执行 网页截图 保存到本地的工作
  • 把获取不到的放到一个躺平列表里,之后再见到这个链接直接放弃
  • 过程中保存日志
网址的 md5 字符串
  • 由于网址可能出现千奇百怪的字符,为了统一并且不会碰撞,采用将网址字符串转换为 md5 字符串的方法
  • 使用 Python 和 JS 中实现 md5 的函数/包完成转换
前端
  • 用 ejs 模板语法与 js MD5 拼接出 MD5 图像链接
代码语言:javascript
复制
<script src="https://101.43.39.125/HexoFiles/js/md5/md5.min.js"> </script>
<img src='<%- theme.vvd_local_links.screecshot_prefix %><%- md5(link_info.link) %>.jpg' alt="<%- link_info.name %>" onerror="this.onerror=null; this.src=this.srcset='<%- theme.vvd_local_links.lost_page %>'">

后端
  • Python 实现 md5
代码语言:javascript
复制
import hashlib
m = hashlib.md5('test'.encode(encoding='utf-8')).hexdigest()

nginx 反向代理提供 https 链接
设置系统开机自动启动服务

ubuntu selenium + chromedriver 网页截图需要 xvfb

创建 shell 脚本

代码语言:javascript
复制
#!/bin/bash

Xvfb :99 -ac -screen 0 1280x1024x24 &
export DISPLAY=:99
/path-to-python /path-to-your-python-script.py

创建 systemctl 服务文件

代码语言:javascript
复制
Description = Service to site image for www.zywvvd.com
After = network.target

[Service]
ExecStart = /usr/bin/bash run_fm.sh
WorkingDirectory = /your-workspace
StandardOutput = inherit
StandardError = inherit
Restart = always
User = lighthouse

[Install]
WantedBy=multi-user.target

设置开机启动

代码语言:javascript
复制
sudo systemctl enable <your-service-name>.service

保存截图

在保存文件的目录下可以看到保存的截图文件

代码语言:javascript
复制
FileManager$ ls screenshots/
33a74bc3a5d45da92630a8fc22b24e53.jpg  82e4d834406a37981f2c701a362ac814.jpg  cb88ee5fdb88a8e5ef7fc5c001d42d17.jpg
56ad8422f9b9c0bbca264e7f6994e4c1.jpg  8e120cf7f45cc0e217c547280c597acf.jpg  e81c1f5749545c5f7d247b3a100ffe62.jpg
73cac8a8906097ccc1c98b92213edaf6.jpg  c2e0ee8b940ec3d3da9cacb40a0dad75.jpg

参考资料

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023年2月25日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 实现思路
  • 实现步骤
    • web 截图环境配置
      • 前端发送网址列表
        • 搭建后端
          • 网址的 md5 字符串
            • 前端
            • 后端
          • nginx 反向代理提供 https 链接
            • 设置系统开机自动启动服务
            • 保存截图
            • 参考资料
            相关产品与服务
            容器服务
            腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档