python写的api系统

     python写的api系统系统用的flask加html加css

没错就是html加flask和css写的前端

开发环境python3.10.9加win11加Redis

Flask==2.3.3

Flask-SQLAlchemy==3.1.1

Flask-Login==0.6.2

redis==5.0.1

urllib3==1.26.16

flask_sqlalchemy==3.1.1

Jinja2==3.1.2

上面是用到的库

你们可以自己配置安装不会安装python的可以用

curl -O https://ghproxy.com/https://raw.githubusercontent.com/lx969788249/lxspacepy/master/pyinstall.sh && chmod +x pyinstall.sh && ./pyinstall.sh

这个是centos系统用的

主要需要root权限

主代码下面是py主代码

import requests
from flask import Flask, render_template, request, redirect, url_for, flash, jsonify, session
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from datetime import datetime
import secrets
import random
from flask import jsonify
import redis
from flask import Flask, request, jsonify

redis_host = 'localhost'  # Redis服务器主机
redis_port = 6379  # Redis服务器端口
redis_db = 0  # Redis数据库编号
cache_timeout = 1  # 缓存超时时间(默认:300秒或5分钟)

redis_conn = redis.StrictRedis(host=redis_host, port=redis_port, db=redis_db)


app = Flask(__name__)
app.config['SECRET_KEY'] = 'jiami'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///D:/sql/test.db'

db = SQLAlchemy(app)
login_manager = LoginManager(app)
login_manager.login_view = 'login'

# 用户
class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    password = db.Column(db.String(80), nullable=False)
    api_key = db.Column(db.String(16), unique=True, nullable=False)
    points = db.Column(db.Integer, default=100)
    call_logs = db.relationship('DailyCallLog', backref='user', lazy=True)
    api_url = db.Column(db.String(255))
    api_timeout = db.Column(db.Integer)
    filtered_addresses = db.Column(db.String(255))

    def generate_api_key(self):
        self.api_key = secrets.token_hex(8)

# 每日调用日志
class DailyCallLog(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    date = db.Column(db.Date, nullable=False)
    call_count = db.Column(db.Integer, default=0)

# API请求日志
class APILog(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    timestamp = db.Column(db.DateTime, default=datetime.utcnow)
    url = db.Column(db.String(255))
    duration = db.Column(db.Float)
    client_ip = db.Column(db.String(20))

@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

@app.route('/')
def home():
    return render_template('sy.html')

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']

        # 输入验证
        if len(username) > 20 or len(password) > 20:
            flash('用户名和密码不能超过20个字符。', 'danger')
            return redirect(url_for('sb_page'))  # 在登录失败时重定向到 sb.html

        user = User.query.filter_by(username=username).first()
        if user and user.password == password:
            login_user(user)
            flash('登录成功!', 'success')
            return redirect(url_for('dashboard'))
        else:
            flash('登录失败,请检查您的凭据。', 'danger')
            return redirect(url_for('sb_page'))  # 在登录失败时重定向到 sb.html 页面
    return render_template('login.html')

@app.route('/sb_page')
def sb_page():
    return render_template('sb.html')

@app.route('/dashboard')
@login_required
def dashboard():
    user_points = current_user.points
    today = datetime.utcnow().date()
    user_id = current_user.id

    daily_call_log = DailyCallLog.query.filter_by(user_id=user_id, date=today).first()

    if daily_call_log is None:
        daily_call_log = DailyCallLog(user_id=user_id, date=today)
        db.session.add(daily_call_log)
        db.session.commit()

    calls_today = daily_call_log.call_count

    api_logs = APILog.query.filter_by(user_id=user_id).order_by(APILog.timestamp.desc()).limit(10)

    return render_template('info.html', username=current_user.username, user_points=user_points, calls_today=calls_today, api_logs=api_logs)

@app.route('/logout')
@login_required
def logout():
    logout_user()
    flash('成功登出!', 'success')
    return redirect(url_for('login'))

@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        if len(username) > 15:
            flash('用户名不能超过15个字符。', 'danger')
            return redirect(url_for('zcsb'))  # 302跳转到zcsb.html页面
        existing_user = User.query.filter_by(username=username).first()
        if existing_user:
            flash('用户名已存在,请选择另一个用户名。', 'danger')
            return redirect(url_for('zcsb'))  # 302跳转到zcsb.html页面
        else:
            admin_user = User.query.filter_by(username='admin').first()
            if admin_user:
                api_url = admin_user.api_url
                api_timeout = admin_user.api_timeout
            else:
                api_url = '默认的API URL'
                api_timeout = 10

            user_key = secrets.token_hex(8)
            new_user = User(username=username, password=password, api_key=user_key, api_url=api_url, api_timeout=api_timeout)
            initial_points = 100
            new_user.points = initial_points
            db.session.add(new_user)
            db.session.commit()

            flash('注册成功!请登录。', 'success')
            return redirect(url_for('login'))
    return render_template('register.html')

@app.route('/zcsb')
def zcsb():
    # 渲染zcsb.html页面
    return render_template('zcsb.html')

@app.route('/admin_login', methods=['GET', 'POST'])
def admin_login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        if username == 'admin' and password == '123456':
            session['admin'] = True
            flash('后台登录成功!', 'success')
            return redirect(url_for('admin_dashboard'))
        else:
            flash('后台登录失败,请检查您的凭据。', 'danger')
    return render_template('admin_login.html')

@app.route('/admin_dashboard', methods=['GET', 'POST'])
@login_required
def admin_dashboard():
    if 'admin' not in session or not session['admin']:
        flash('您没有权限访问该页面。', 'danger')
        return redirect(url_for('login'))

    if request.method == 'POST':
        filtered_addresses = request.form.get('filtered_addresses')
        current_user.filtered_addresses = filtered_addresses
        db.session.commit()
        flash('过滤地址已成功更新!', 'success')

    return render_template('admin_dashboard.html', username=current_user.username, current_api_url=current_user.api_url, current_api_timeout=current_user.api_timeout, filtered_addresses=current_user.filtered_addresses)

app = Flask(__name__)
app.config['SECRET_KEY'] = 'jiami'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///D:/sql/test.db'

db = SQLAlchemy(app)
login_manager = LoginManager(app)
login_manager.login_view = 'login'

# 用户
class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    password = db.Column(db.String(80), nullable=False)
    api_key = db.Column(db.String(16), unique=True, nullable=False)
    points = db.Column(db.Integer, default=100)
    call_logs = db.relationship('DailyCallLog', backref='user', lazy=True)
    api_url = db.Column(db.String(255))
    api_timeout = db.Column(db.Integer)

    def generate_api_key(self):
        self.api_key = secrets.token_hex(8)

# 每日调用日志
class DailyCallLog(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    date = db.Column(db.Date, nullable=False)
    call_count = db.Column(db.Integer, default=0)

# API请求日志
class APILog(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    timestamp = db.Column(db.DateTime, default=datetime.utcnow)
    url = db.Column(db.String(255))
    duration = db.Column(db.Float)
    client_ip = db.Column(db.String(20))

@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

@app.route('/')
def home():
    return render_template('sy.html')

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']

        # 输入验证
        if len(username) > 20 or len(password) > 20:
            flash('用户名和密码不能超过20个字符。', 'danger')
            return redirect(url_for('sb_page'))  # 在登录失败时重定向到 sb.html

        user = User.query.filter_by(username=username).first()
        if user and user.password == password:
            login_user(user)
            flash('登录成功!', 'success')
            return redirect(url_for('dashboard'))
        else:
            flash('登录失败,请检查您的凭据。', 'danger')
            return redirect(url_for('sb_page'))  # 在登录失败时重定向到 sb.html 页面
    return render_template('login.html')

@app.route('/sb_page')
def sb_page():
    return render_template('sb.html')

@app.route('/dashboard')
@login_required
def dashboard():
    user_points = current_user.points
    today = datetime.utcnow().date()
    user_id = current_user.id

    daily_call_log = DailyCallLog.query.filter_by(user_id=user_id, date=today).first()

    if daily_call_log is None:
        daily_call_log = DailyCallLog(user_id=user_id, date=today)
        db.session.add(daily_call_log)
        db.session.commit()

    calls_today = daily_call_log.call_count

    api_logs = APILog.query.filter_by(user_id=user_id).order_by(APILog.timestamp.desc()).limit(10)

    return render_template('info.html', username=current_user.username, user_points=user_points, calls_today=calls_today, api_logs=api_logs)

@app.route('/logout')
@login_required
def logout():
    logout_user()
    flash('成功登出!', 'success')
    return redirect(url_for('login'))

@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        if len(username) > 15:
            flash('用户名不能超过15个字符。', 'danger')
            return redirect(url_for('zcsb'))  # 302跳转到zcsb.html页面
        existing_user = User.query.filter_by(username=username).first()
        if existing_user:
            flash('用户名已存在,请选择另一个用户名。', 'danger')
            return redirect(url_for('zcsb'))  # 302跳转到zcsb.html页面
        else:
            admin_user = User.query.filter_by(username='admin').first()
            if admin_user:
                api_url = admin_user.api_url
                api_timeout = admin_user.api_timeout
            else:
                api_url = '默认的API URL'
                api_timeout = 10

            user_key = secrets.token_hex(8)
            new_user = User(username=username, password=password, api_key=user_key, api_url=api_url, api_timeout=api_timeout)
            initial_points = 100
            new_user.points = initial_points
            db.session.add(new_user)
            db.session.commit()

            flash('注册成功!请登录。', 'success')
            return redirect(url_for('login'))
    return render_template('register.html')

@app.route('/zcsb')
def zcsb():
    # 渲染zcsb.html页面
    return render_template('zcsb.html')

@app.route('/admin_login', methods=['GET', 'POST'])
def admin_login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        if username == 'admin' and password == '123456':
            session['admin'] = True
            flash('后台登录成功!', 'success')
            return redirect(url_for('admin_dashboard'))
        else:
            flash('后台登录失败,请检查您的凭据。', 'danger')
    return render_template('admin_login.html')

@app.route('/admin_dashboard', methods=['GET', 'POST'])
@login_required
def admin_dashboard():
    if 'admin' not in session or not session['admin']:
        flash('您没有访问该页面的权限。', 'danger')
        return redirect(url_for('login'))

    if request.method == 'POST':
        api_url = request.form.get('api_url')
        api_timeout = request.form.get('api_timeout')

        User.query.update({'api_url': api_url, 'api_timeout': api_timeout})
        db.session.commit()

        flash('API设置已保存!', 'success')

    return render_template('admin_dashboard.html', username=current_user.username, current_api_url=current_user.api_url, current_api_timeout=current_user.api_timeout)
@app.route('/user_list', methods=['GET'])
@login_required
def user_list():
    if 'admin' not in session or not session['admin']:
        flash('您没有访问该页面的权限。', 'danger')
        return redirect(url_for('login'))

    page = request.args.get('page', 1, type=int)
    users = User.query.paginate(page=page, per_page=20)

    return render_template('user_list.html', users=users)

@app.route('/update_user', methods=['POST'])
@login_required
def update_user():
    if 'admin' not in session or not session['admin']:
        flash('您没有访问该页面的权限。', 'danger')
        return redirect(url_for('login'))

    user_id = request.form.get('user_id')
    new_password = request.form.get('new_password')
    new_api_key = request.form.get('new_api_key')

    user = User.query.get(user_id)

    if user:
        if new_password:
            user.password = new_password
        if new_api_key:
            user.api_key = new_api_key

        db.session.commit()
        flash('用户信息已更新!', 'success')
    else:
        flash('无效的用户ID。', 'danger')

    return redirect(url_for('user_list'))
@app.route('/update_user_points', methods=['POST'])
@login_required
def update_user_points():
    if 'admin' not in session or not session['admin']:
        flash('您没有访问该页面的权限。', 'danger')
        return redirect(url_for('login'))

    user_id = request.form.get('user_id')
    new_points = request.form.get('new_points')

    user = User.query.get(user_id)

    if user:
        user.points = int(new_points)
        db.session.commit()
        flash('用户点数已更新!', 'success')
    else:
        flash('无效的用户ID。', 'danger')

    return redirect(url_for('user_list'))



@app.route('/api', methods=['GET'])
def get_external_url():
    api_key = request.args.get('key')
    requested_url = request.args.get('url')

    user = User.query.filter_by(api_key=api_key).first()

    if user:
        filtered_addresses = set(user.filtered_addresses.split(',')) if user.filtered_addresses else set()
        if requested_url in filtered_addresses:
            return jsonify({'code': 405, 'msg': '地址已被过滤'}), 405
        try:
            if user.points <= 0:
                return jsonify({'code': 401, 'diansbuz': '点数不足'}), 402

            api_urls = user.api_url.split(',')
            random.shuffle(api_urls)

            for api_url in api_urls:
                full_api_url = api_url + requested_url
                api_timeout = user.api_timeout or 10

                start_time = datetime.now()
                try:
                    response = requests.get(full_api_url, timeout=api_timeout)
                    response.raise_for_status()
                except requests.exceptions.RequestException as e:
                    continue

                end_time = datetime.now()
                duration = (end_time - start_time).total_seconds()

                api_log = APILog(user_id=user.id, timestamp=end_time, url=requested_url, duration=duration,
                                 client_ip=request.remote_addr)
                db.session.add(api_log)
                db.session.commit()

                if response.status_code == 200:
                    api_data = response.json()
                    url = api_data.get('url')

                    if url:
                        user.points -= 1
                        db.session.commit()

                        today = datetime.utcnow().date()
                        daily_call_log = DailyCallLog.query.filter_by(user_id=user.id, date=today).first()

                        if daily_call_log:
                            daily_call_log.call_count += 1
                        else:
                            daily_call_log = DailyCallLog(user_id=user.id, date=today, call_count=1)

                        db.session.add(daily_call_log)
                        db.session.commit()

                        # 成功获取到URL后才设置缓存键
                        cache_key = f'api_endpoint1:{requested_url}'
                        redis_conn.setex(cache_key, cache_timeout, url)

                        return jsonify({'code': 200, 'msg': 'success', 'type': 'm3u8', 'url': url})
                    else:
                        return jsonify({'code': 402, 'murl': '未找到URL'})
                else:
                    return jsonify({'code': 403, 'ban': 'API请求失败'})

            # 所有API接口请求失败
            return jsonify({'code': 404, 'apiban': '所有API接口请求失败'})

        except requests.exceptions.RequestException as e:
            return jsonify({'code': 500, 'cw': 'API请求出错'})

    else:
        return jsonify({'code': 401, 'weux': '无效的API密钥'}), 401
@app.route('/change_api_key', methods=['POST'])
@login_required
def change_api_key():
    user = current_user
    user.generate_api_key()
    db.session.commit()
    flash('API 密钥已更换!', 'success')
    return redirect(url_for('dashboard'))

if __name__ == '__main__':
    with app.app_context():
        db.create_all()
    app.run(debug=True)

@app.route('/api', methods=['GET'])
def get_external_url():
    api_key = request.args.get('key')
    requested_url = request.args.get('url')
    cache_key = f'api_endpoint1:{requested_url}'

    cached_url = redis_conn.get(cache_key)

    if cached_url:
        return jsonify({'code': 200, 'msg': 'success', 'type': 'm3u8', 'url': cached_url.decode('utf-8')})

    user = User.query.filter_by(api_key=api_key).first()

    if user:
        filtered_addresses = set(user.filtered_addresses.split(',')) if user.filtered_addresses else set()
        if requested_url in filtered_addresses:
            return jsonify({'code': 405, 'msg': '地址已被过滤'}), 405
        try:
            if user.points <= 0:
                return jsonify({'code': 401, 'diansbuz': '点数不足'}), 402

            api_urls = user.api_url.split(',')  
            random.shuffle(api_urls)  

            for api_url in api_urls:
                full_api_url = api_url + requested_url
                api_timeout = user.api_timeout or 10

                start_time = datetime.now()
                try:
                    response = requests.get(full_api_url, timeout=api_timeout)
                    response.raise_for_status()
                except requests.exceptions.RequestException as e:
                    continue

                end_time = datetime.now()
                duration = (end_time - start_time).total_seconds()

                api_log = APILog(user_id=user.id, timestamp=end_time, url=requested_url, duration=duration, client_ip=request.remote_addr)
                db.session.add(api_log)
                db.session.commit()

                if response.status_code == 200:
                    api_data = response.json()
                    url = api_data.get('url')

                    if url:
                        user.points -= 1
                        db.session.commit()

                        today = datetime.utcnow().date()
                        daily_call_log = DailyCallLog.query.filter_by(user_id=user.id, date=today).first()

                        if daily_call_log:
                            daily_call_log.call_count += 1
                        else:
                            daily_call_log = DailyCallLog(user_id=user.id, date=today, call_count=1)

                        db.session.add(daily_call_log)
                        db.session.commit()

                        # 返回成功的JSON响应
                        redis_conn.setex(cache_key, cache_timeout, url)

                        return jsonify({'code': 200, 'msg': 'success', 'type': 'm3u8', 'url': url})
                    else:
                        return jsonify({'code': 402, 'murl': '未找到URL'})
                else:
                    return jsonify({'code': 403, 'ban': 'API请求失败'})

            # 所有API接口请求失败
            return jsonify({'code': 404, 'apiban': '所有API接口请求失败'})

        except requests.exceptions.RequestException as e:
            return jsonify({'code': 500, 'cw': 'API请求出错'})

    else:
        return jsonify({'code': 401, 'weux': '无效的API密钥'}), 401

@app.route('/change_api_key', methods=['POST'])
@login_required
def change_api_key():
    user = current_user
    user.generate_api_key()
    db.session.commit()
    flash('API 密钥已更换!', 'success')
    return redirect(url_for('dashboard'))

if __name__ == '__main__':
    with app.app_context():
        db.create_all()
    app.run(debug=True)

html代码和css代码我打包在123网盘上https://www.123pan.com/s/xIRRVv-Lg6Qh.html

下面是api系统的部分截图

宝塔pm2来启动监控项目

161行修改后台用户名和登录密码注意这里有一个bug是在前台登录同样的用户名才开源对所有的用户进行api和时间的控制这可能是一个bug后面可能会去修复--

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值