帆软调用api

原文章:http://t.csdnimg.cn/ZrFJJ
https://blog.csdn.net/weixin_44556829/article/details/132294329?spm=1001.2014.3001.5506
原因:写出来的python脚本不能被FR直接使用
方案:用Python制作API,通过FR的JS脚本调用这个API,从而实现实时调用。
1. 使用Python的Falsk框架编写API接口

原文章代码如下:

点击查看代码
# -*- coding: UTF-8 -*-
# @Author : JW-Panda-数据分析师
 
from flask import Flask  # 框架
from flask_cors import CORS  # 实现跨域
from gevent import pywsgi  # 使用WSGI启动服务
import win32api, win32gui  # 静默运行
import time, os  # 时间及控制台命令
import logging  # 日志记录
 
# 静默模式运行
ct = win32api.GetConsoleTitle()
hd = win32gui.FindWindow(0, ct)
win32gui.ShowWindow(hd, 0)
 
# Flask 架构
app = Flask(__name__)  # 获取实例
CORS(app)  # 解决跨域问题
 
 
def check_pid(port):
    """
    查找被占用端口并杀掉重置
    :param port: 端口号
    :return: 无返回
    """
    try:
        r = os.popen("netstat -ano | findstr " + port)
        PID = r.read().split()[-1]
        print("端口占用,关闭端口重新执行。")
        os.system("taskkill /PID " + str(PID) + " /T /F")
    except:
        print('端口未被占用,API正常运行')
        pass
 
 
def save_record():
    logging.basicConfig(filename='.\Api_use.log',
                        filemode='a', level=logging.INFO, datefmt='%a, %d %b %Y %H:%M:%S')
 
 
# <a>是带参传入,如果有参数则放到这里,<int:a>表示传入int类型,多参数用“/”依次往后
@app.route("/test/<a>", methods=["GET"])  # 指定外网访问的路径和方式
def test(a):  # a是带参传入
    # 此处放入python程序
    runtime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
    if a:
        pass
    x = str(runtime) + "_test_" + str(a)
    logging.info(x)
    return x  # x为需要返回的数据
 
 
if __name__ == '__main__':
    """
    关于本机IP,可以通过cmd的【ipconfig】查找以太网适配器的ipv4地址,可能需要提前设置UDP转发
    关于端口号:可以通过cmd的【netstat】命令,根据ip找到对应的端口,自定义一个从来没从过的,范围[0-65535],避开常用
    """
    print('{:-^30}'.format('接口开始运行'))
    save_record()  # 开始记录日志
    host = '111.111.111.111'  # 这里替换你的IP
    port = '55333'  # 这里替换你的端口
    check_pid(port)  # 检查端口占用
    print('http://{}:{}/'.format(host, int(port)))
    server = pywsgi.WSGIServer((host, int(port)), app)  # 使用WSGI启动服务
    server.serve_forever()
    # app.run(host="10.1.175.107", port=62013, debug=True)  # 默认,调试使用
下载PyCharm

在这个界面添加各种模块,新建工程,无脑化的将代码粘入

将上面的代码修改下,修改的内容为

host = '127.0.0.1' # 这里替换你的IP port = '12345' # 这里替换你的端口

点击查看代码
# -*- coding: UTF-8 -*-
# @Author : JW-Panda-数据分析师

from flask import Flask  # 框架
from flask_cors import CORS  # 实现跨域
from gevent import pywsgi  # 使用WSGI启动服务
import win32api, win32gui  # 静默运行
import time, os  # 时间及控制台命令
import logging  # 日志记录

# 静默模式运行
ct = win32api.GetConsoleTitle()
hd = win32gui.FindWindow(0, ct)
win32gui.ShowWindow(hd, 0)

# Flask 架构
app = Flask(__name__)  # 获取实例
CORS(app)  # 解决跨域问题


def check_pid(port):
    """
    查找被占用端口并杀掉重置
    :param port: 端口号
    :return: 无返回
    """
    try:
        r = os.popen("netstat -ano | findstr " + port)
        PID = r.read().split()[-1]
        print("端口占用,关闭端口重新执行。")
        os.system("taskkill /PID " + str(PID) + " /T /F")
    except:
        print('端口未被占用,API正常运行')
        pass


def save_record():
    logging.basicConfig(filename='.\Api_use.log',
                        filemode='a', level=logging.INFO, datefmt='%a, %d %b %Y %H:%M:%S')


# <a>是带参传入,如果有参数则放到这里,<int:a>表示传入int类型,多参数用“/”依次往后
@app.route("/test/<a>", methods=["GET"])  # 指定外网访问的路径和方式
def test(a):  # a是带参传入
    # 此处放入python程序
    runtime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
    if a:
        pass
    x = str(runtime) + "_test_" + str(a)
    logging.info(x)
    return x  # x为需要返回的数据


if __name__ == '__main__':
    """
    关于本机IP,可以通过cmd的【ipconfig】查找以太网适配器的ipv4地址,可能需要提前设置UDP转发
    关于端口号:可以通过cmd的【netstat】命令,根据ip找到对应的端口,自定义一个从来没从过的,范围[0-65535],避开常用
    """
    print('{:-^30}'.format('接口开始运行'))
    save_record()  # 开始记录日志
    host = '127.0.0.1'  # 这里替换你的IP
    port = '12345'  # 这里替换你的端口
    check_pid(port)  # 检查端口占用
    print('http://{}:{}/'.format(host, int(port)))
    server = pywsgi.WSGIServer((host, int(port)), app)  # 使用WSGI启动服务
    server.serve_forever()
    # app.run(host="10.1.175.107", port=62013, debug=True)  # 默认,调试使用

点击绿色的运行按钮,看到下面的运行信息
------------接口开始运行------------
端口未被占用,API正常运行
http://127.0.0.1:12345/

好的,正常运行。

  1. 测试API是否生效

直接在浏览器上输入http://127.0.0.1:12345/,会报错

看下程序里,

访问的地址应为http://127.0.0.1:12345/test/abcd

看到返回结果,说明没问题了。

  1. 帆软编写js实现调用

结果输出框控件,控件名称为textEditor0,
新建一个按钮,设置点击事件,选择js脚本,下面是代码

点击查看代码
// 获取参数(如果有)
var canshu = _g().parameterEl.getWidgetByName("textEditor1").getValue();
// 目标网址
const url = 'http://127.0.0.1:12345/test/a';
//run_script?script=D:/kettle/jibiao/home_business_security.bat
reportURL = encodeURI(url);
// 创建一个新的 XMLHttpRequest 对象
const xhr = new XMLHttpRequest();
// 设置请求方法和目标 URL
xhr.open('GET', reportURL, true);
// 监听请求状态变化

xhr.onreadystatechange = function () {
  // 当请求状态为完成时
  if (xhr.readyState === XMLHttpRequest.DONE) {
    // 确保请求成功
    if (xhr.status === 200) {
      console.log('Response:', xhr.responseText);
      // 赋予控件实际值
      kongjian= _g().parameterEl.getWidgetByName("textEditor0");
      kongjian.setValue("Response:"+xhr.responseText,false);
    } else {
      console.error('Error:', xhr.status, xhr.statusText);
    }
  }
};
// 发送请求
xhr.send();
// 刷新页面
setTimeout(function() {_g().parameterCommit(); }, 500)

预览之后得到如下结果:

说明整个功能是正常使用的

本地测试没问题,下面将端口程序放到远端服务器,进行测试。

1.将 Python 程序打包成独立的可执行文件
打开cmd ,输入pip install pyinstaller,进行安装
对命名为123.py的文件进行打包,在pycharm的控制台输入pyinstaller -F 123.py ,一般生成的exe文件存储在当前目录的dist文件内

生成的123.exe放到服务器上,远程访问失败,应该是 host = '127.0.0.1' 这出问题,改为 host = '0.0.0.0' 这是因为0.0.0.0 允许任何网络接口的访问,而 127.0.0.1 仅允许本机访问。

改后访问http://172.23.255.164:12345/test/1,功能正常。如下图所示

但是访问https://172.23.255.164:12345/test/1,则返回错误

HTTP访问正常但HTTPS访问错误,这可能是因为Flask应用没有配置SSL/TLS证书来支持HTTPS,因为中台的页面是https打开的,所以接下来配置下SSL/TLS来支持HTTPS

我的服务端SSL证书是JAVA版的jks证书,

转换的参考资料:
https://www.baeldung.com/java-keystore-convert-to-pem-format

我操作的步骤
keytool -list -keystore keystore.jks

keytool -exportcert -alias 1 -keystore 172_16_100_14.jks -rfc -file first-key-pair-cert.pem

将生成的first-key-pair-cert.pem和服务器端的172_16_100_14.pem分别重命名为cet.pem和key.pem

打开PCcharm,粘贴以下代码,password 替换成自己的密钥。

点击查看代码
import subprocess
from flask import Flask, jsonify, request
from gevent import pywsgi, monkey
from flask_cors import CORS
import ssl

app = Flask(__name__)
CORS(app)


def run_bat(filename):
    p = subprocess.Popen("cmd.exe /c" + filename, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

    output = ''
    curline = p.stdout.readline()
    while (curline != b''):
        output += curline.decode()  # decode from bytes to string
        curline = p.stdout.readline()

    p.wait()

    return output, p.returncode


@app.route("/")
def hello():
    return jsonify(message="Hello World!")


@app.route('/run_script')
def run_script():
    script_path = request.args.get('script')  # get script path from URL parameters
    output, returncode = run_bat(script_path)
    return jsonify(output=output, returncode=returncode)


if __name__ == "__main__":
    host = '0.0.0.0'
    port = 22345
    certfile = './crt.pem'
    keyfile = './key.pem'
    password = '你的密钥'

    monkey.patch_all()

    context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
    context.load_cert_chain(certfile=certfile, keyfile=keyfile, password=password)

    server = pywsgi.WSGIServer((host, port), app, ssl_context=context)

    print(f'Starting server at https://{host}:{port}')
    server.serve_forever()

将py文件生成exe,我的文件是main_bat.py,将main_bat.py,cet.pem和key.pem放到服务器的一个文件夹里。

双击main_bat.exe启动

启动后使用命令查看端口状态
netstat -aon | findstr /i listening

访问服务器端地址

可以正常访问

可以执行服务器端的bat文件
https://172.11.11.119:22345/run_script?script=D:\kettle\jibiao\zidong_jibiao_jici.bat

url使用参数:
https://172.XX.XXX.XX:22345/run_script?script=D:\kettle\jibiao_forgongdan2_arg\zidong_jibiao_jici.bat p1=通化梅河口支撑服务中心

调用的bat修改下:

点击查看代码
@echo off

setlocal EnableDelayedExpansion


chcp 65001


set paramm=%*


set "hour=%time:~0,2%"

if "%hour:~0,1%"==" " set "hour=0%hour:~1,1%"


set "timestamp=%date:~0,4%%date:~5,2%%date:~8,2%%hour%%time:~3,2%%time:~6,2%"


D:
cd D:\kettle\data-integration

kitchen.bat -rep lj -user admin -pass admin -dir /forgongdan2_arg -job zidong_jibiao_jici -param:"%paramm%" -level=basic> D:\zidong_log\arg_zidong_jibiao_jici_%timestamp%.log

这样就实现了传参调用服务器上的bat文件,bat文件调用kettle。直线帆软和kettle的联动。当然kettle也需要加个命名参数p1,在表输入里增加条件 hsdw = COALESCE(NULLIF('${p1}', ''), hsdw)

posted @ 2024-07-24 14:42  铭泽1988  阅读(300)  评论(0)    收藏  举报