You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Flask的Web应用:为NMAP扫描添加HTML进度条的实现方法问询

实现Flask+NMAP扫描的进度条展示

看起来你需要解决两个核心问题:异步处理耗时的NMAP扫描避免阻塞请求,以及在前端实时展示扫描进度。另外Network.html无法展示的问题大概率是路由配置或静态文件加载的问题,我会一起覆盖到。

第一步:重构后端为异步扫描(避免请求阻塞)

你的当前代码是同步执行NMAP扫描,这会导致Flask请求一直挂起直到扫描完成,根本没法返回进度。我们可以用后台线程来处理扫描任务,同时用一个全局字典来跟踪任务进度(生产环境建议用Redis这类缓存,这里先给简单入门版本)。

修改后的Discovery1.py(整合Flask逻辑):

from flask import Flask, render_template, jsonify, request
import nmap
import pandas as pd
import threading

app = Flask(__name__)

# 存储扫描任务的进度,key是任务ID,value是进度百分比/状态码
scan_progress = {}
task_counter = 0

def run_nmap_scan(task_id, target):
    global scan_progress
    scan_progress[task_id] = 0
    ns = nmap.PortScanner()
    
    # 自定义进度跟踪逻辑(NMAP本身无原生进度回调,按扫描阶段拆分)
    try:
        # 阶段1:主机发现(占30%进度)
        scan_progress[task_id] = 10
        ns.scan(hosts=target, arguments='-sn')  # 仅执行ping扫描
        scan_progress[task_id] = 30
        
        # 阶段2:存活主机端口扫描(占60%进度)
        alive_hosts = [host for host in ns.all_hosts() if ns[host].state() == 'up']
        if not alive_hosts:
            scan_progress[task_id] = 100
            return
        
        total_hosts = len(alive_hosts)
        scanned_hosts = 0
        
        for host in alive_hosts:
            scanned_hosts += 1
            # 按已扫描主机比例更新进度
            scan_progress[task_id] = 30 + int((scanned_hosts / total_hosts) * 60)
            ns.scan(hosts=host, arguments='-p 1-1000')  # 扫描常用端口范围
        
        # 阶段3:结果保存(占10%进度)
        scan_progress[task_id] = 90
        with open('results.csv', 'w') as f:
            f.write(ns.csv())
        df = pd.read_csv("results.csv", delimiter=";")
        df.to_csv("results.csv", index=None)
        scan_progress[task_id] = 100
    except Exception as e:
        scan_progress[task_id] = -1  # 用-1标记扫描失败

@app.route('/')
def index():
    return render_template('Network.html')  # 确保模板放在templates文件夹下

@app.route('/start-scan', methods=['POST'])
def start_scan():
    global task_counter
    task_id = f"task_{task_counter}"
    task_counter += 1
    target = request.json.get('target', '10.0.0.0/24')
    # 启动后台线程执行扫描,daemon=True确保线程随主进程退出
    threading.Thread(target=run_nmap_scan, args=(task_id, target), daemon=True).start()
    return jsonify({"task_id": task_id})

@app.route('/get-progress/<task_id>')
def get_progress(task_id):
    progress = scan_progress.get(task_id, 0)
    return jsonify({"progress": progress})

if __name__ == '__main__':
    app.run(debug=True)

第二步:前端实现进度条和页面展示

首先确保Network.html放在Flask项目根目录下的templates文件夹里(Flask默认模板路径,没有的话新建一个)。然后在页面中添加进度条组件,用JavaScript轮询后端接口更新进度。

示例Network.html代码:

<!DOCTYPE html>
<html>
<head>
    <title>NMAP扫描进度展示</title>
    <style>
        .progress-wrap {
            width: 80%;
            margin: 30px auto;
            border: 1px solid #ddd;
            border-radius: 6px;
            overflow: hidden;
        }
        .progress-bar {
            height: 32px;
            background-color: #2196F3;
            width: 0%;
            transition: width 0.3s ease;
            text-align: center;
            color: white;
            line-height: 32px;
            font-size: 14px;
        }
        .hidden {
            display: none;
        }
        .control-area {
            text-align: center;
            margin-top: 20px;
        }
        .control-area input {
            padding: 8px 12px;
            width: 300px;
            margin-right: 10px;
        }
        .control-area button {
            padding: 8px 16px;
            cursor: pointer;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
        }
    </style>
</head>
<body>
    <h1 style="text-align:center;">NMAP网络扫描工具</h1>
    <div class="control-area">
        <input type="text" id="targetIp" placeholder="输入目标网段(如10.0.0.0/24)" value="10.0.0.0/24">
        <button onclick="initiateScan()">开始扫描</button>
    </div>
    
    <div class="progress-wrap hidden" id="progressContainer">
        <div class="progress-bar" id="progressBar">0%</div>
    </div>

    <script>
        let pollTimer;

        function initiateScan() {
            const target = document.getElementById('targetIp').value;
            // 发送请求启动扫描任务
            fetch('/start-scan', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({ target: target })
            })
            .then(res => res.json())
            .then(data => {
                const taskId = data.task_id;
                // 显示进度条容器
                document.getElementById('progressContainer').classList.remove('hidden');
                // 每秒轮询一次进度
                pollTimer = setInterval(() => {
                    fetch(`/get-progress/${taskId}`)
                    .then(res => res.json())
                    .then(progressData => {
                        const progress = progressData.progress;
                        const bar = document.getElementById('progressBar');
                        bar.style.width = `${progress}%`;
                        bar.textContent = `${progress}%`;

                        if (progress === 100) {
                            clearInterval(pollTimer);
                            alert('扫描完成!结果已保存至results.csv');
                        } else if (progress === -1) {
                            clearInterval(pollTimer);
                            bar.style.backgroundColor = '#f44336';
                            bar.textContent = '扫描失败,请检查目标或NMAP配置';
                            alert('扫描过程中出现错误,请重试');
                        }
                    });
                }, 1000);
            });
        }
    </script>
</body>
</html>

第三步:解决Network.html无法展示的问题

如果你的页面无法加载,按以下步骤排查:

  • 确认Network.html放在项目根目录的templates文件夹下(没有就新建)
  • 检查Flask的根路由@app.route('/')是否正确返回render_template('Network.html')
  • 启动Flask应用后,通过http://localhost:5000访问页面,不要直接双击打开本地HTML文件
  • 如果页面用到静态资源(如独立的CSS/JS文件),要放在static文件夹下,并用{{ url_for('static', filename='xxx.css') }}引用

生产环境优化提示

  • 后台线程方案仅适合开发环境,生产环境建议用Celery+Redis/RabbitMQ管理异步任务,支持多进程和任务持久化
  • 全局的scan_progress字典在多进程Flask部署中会失效,生产环境请用Redis等分布式存储保存进度
  • NMAP的进度是模拟的,你可以根据实际扫描需求调整阶段划分和进度比例

内容的提问来源于stack exchange,提问作者PioneerPrawn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:11:01