事情是这样的,因为smms的图床有容量限制,不太爽,所以自己在服务器上搭建了一个图床,准备免费公开使用,但是既然是公开,就不免有人上传一些不正常的东西到图床上,所以为了防止诈骗等违规图片搭建了一个基于NsfwJS+Tesseract-ocr+Pyzbra的接口,检测图片内是否含有违规内容

代码

import requests
from flask import Flask, request

app = Flask(__name__)
import validators
import pyzbar.pyzbar as pyzbar
from PIL import Image
import pytesseract

wjcwj = ['你的严重违禁词', '你的违禁词']  # 这里的违禁词出现1次就不过审

wjc = ['你的违禁词', '你的违禁词']  # 这里的违禁词最多出现1次

nsfwjs_level = 50  # Nsfwjs敏感度,越高越敏感


def pdwjc(text):  # 判断违禁词
    wjcn = 0
    for i in wjc:
        if text.find(i) != -1:
            wjcn += 5

    for i in wjcwj:
        if text.find(i) != -1:
            wjcn += 10

    if wjcn == 0:
        print('No wjc')
    else:
        print(str(wjcn) + ' Score Wjc')

    return wjcn


def taeck_ocr(image):  # 获取文字信息并去除换行和空格
    text = pytesseract.image_to_string(image, lang='chi_sim')
    text = str(text).replace(' ', '').replace('\n', '')
    return text


def find_ewm(img):  # 寻找是否有二维码
    try:
        texts = pyzbar.decode(img)
    except OSError:
        return [True, 'Error to try']  # 高并发容易报错,所以加一个Try,报错默认不过审,如果想要报错仍然过审把这行左侧的True改成False
    if not texts:
        print('No Ewm')
        return [False, None]
    for text in texts:
        t = text.data.decode("utf-8")
        if t:
            print('Ewm INFO:' + t)
            return [True, t]


def nsfwjs():  # 调用nsfwjs鉴黄
    url = "http://127.0.0.1:3000/classify"
    with open('st.png', 'rb') as f:
        payload = {"image": f.read()}  # 调用
    response = requests.post(url, files=payload)
    backres = response.json()
    p = float(str("{:.2%}".format(backres["porn"])).replace('%', ''))  # 格式化三个主要鉴黄参数
    h = float(str("{:.2%}".format(backres["hentai"])).replace('%', ''))  # 格式化三个主要鉴黄参数
    s = float(str("{:.2%}".format(backres["sexy"])).replace('%', ''))  # 格式化三个主要鉴黄参数
    percentages = [p, h, s]
    sum_percentages = sum(percentages) / 100  # 计算三个参数的和
    if int(float(str("{:.2%}".format(sum_percentages).replace('%',
                                                              '')))) > nsfwjs_level:  # 判断分数,如果过于敏感可以在顶上nsfwjs_level变量调低,默认设置的是>50%就不过审
        print(('{:.2%}'.format(sum_percentages)) + ' 违规')
        return True  # 一旦违规直接扣10分不过审
    else:
        print(('{:.2%}'.format(sum_percentages)) + ' 不违规')
        return False


@app.route('/', methods=['POST', 'GET'])
def mainstart():  # 主函数
    canupload = 10  # 定义一个合格分数,>0分即可上传,反之禁止

    imgs = request.files['image']  # 从请求中获取图片
    imgs.save('./st.png')  # 保存图片到本地
    imgs.close()  # 关闭图片

    simg = Image.open('st.png')  # PIL打开图片,只打开一次有助于节省资源,也能提高并发

    # 违规图片判断
    if nsfwjs():
        canupload -= 10

    # 图片中含有网址二维码判断
    bfind_ewm = find_ewm(simg)
    if bfind_ewm[0]:
        if validators.url(bfind_ewm[1]):
            canupload -= 10

    # 违禁词判断
    btaeck_ocr = taeck_ocr(simg)
    bpfwjc = pdwjc(btaeck_ocr)
    canupload -= bpfwjc

    # 判断最终分数
    if canupload <= 0:
        print('不合格,禁止上传,Score:' + str(canupload))
        backdata = {'porn': 1.00000, 'hentai': 1.00000, 'sexy': 1.00000, 'drawing': 0.00000,
                    'neutral': 0.00000}  # LskyPro不支持接入自定义接口,所以仿造一个NsfwJS的接口返回来实现过审和不过审回报
    else:
        print('合格,允许上传,Score:' + str(canupload))
        backdata = {'porn': 0.00000, 'hentai': 0.00000, 'sexy': 0.00000, 'drawing': 0.00000,
                    'neutral': 1.00000}  # LskyPro不支持接入自定义接口,所以仿造一个NsfwJS的接口返回来实现过审和不过审回报
    simg.close()  # 关闭图片
    return backdata


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=54125)

到手之后可以根据注释更改如下变量,wjcjc:严重级违禁词,wjc:一般违禁词,nsfwjs_level:Nsfwjs敏感度

环境部署

环境:Centos 7.9

NsfwJS

一般可以使用docker部署NsfwJS,这是最简单的

以下参考这位大神:NSFW-API 开源的图片鉴黄API - ROYWANG

在宝塔环境中安装Docker管理器,导入镜像

看到在运行中就行了

Tesseract-ocr

Centos安装Tesseract-OCR比较复杂,有很多坑

参考:centos下tesseract-ocr的安装 - 稀土掘金

这里过程就不详细讲了,可以去看上面的文章,列举一下踩的坑

1.C++会话版本错误

Your compiler does not have the necessary C++17 support!

这个错误一般是在编译过程出现的,解决方法:

在SSH依次运行

yum install -y centos-release-scl
yum install devtoolset-8-gcc*
scl enable devtoolset-8 bash

然后再编译就可以了

2.Leptonica环境变量错误

这个错误也是在编译过程中出现的

解决方法:

在SSH中vim /etc/profile,然后在最后添加如下设置

export LD_LIBRARY_PATH=$LD_LIBRARY_PAYT:/usr/local/lib
export LIBLEPT_HEADERSDIR=/usr/local/include
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig

保存退出,输入如下指令,使环境变量生效

source /etc/profile

3.环境变量or字体错误

pytesseract.pytesseract.TesseractError: (1, u'Tesseract Open Source OCR Engine v3.04.00 with Leptonica Error opening data file /usr/local/share/tessdata/eng.traineddata Please make sure the TESSDATA_PREFIX environment variable is set to the parent directory of your "tessdata" directory. Failed loading language \'eng\' Tesseract couldn\'t load any languages! Could not initialize tesseract.')

这个错误是在代码运行时出现的,一般原因有两种,一种是环境变量错误,另一种是字体文件有问题,解决方法也很简单,重新去github下载字体文件,然后再在SSH里vim打开/etc/profile文件,在最后添加如下设置

export TESSDATA_PREFIX=/usr/local/share/tessdata

保存退出,输入如下指令,使环境变量生效

source /etc/profile

这两个环境装好就可以运行了