基于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
相关产品推荐
相关产品推荐

