IP扫描,局域网内扫描IP地址,找出有用,未使用的。正在使用的信息
- 扫描放在独立线程→ 界面永远能动
- 控制并发 ping 数量→ 不爆 CPU
- 分段执行 + 自动等待→ Windows 轻松处理
- 超时时间缩短→ 扫描更快
不用驱动、不用管理员、不用 npcap、不卡死!
扫描局域网 IP
显示 MAC 地址
显示网卡厂商
显示本机网卡信息
图形界面窗口
不用安装任何驱动(npcap/winpcap)
不用管理员权限
import subprocess import re import requests import tkinter as tk from tkinter import ttk, scrolledtext, messagebox import threading import time MAC_API = "https://api.macvendors.com/" def get_subnet(): try: ipconfig = subprocess.check_output( "ipconfig", shell=True, text=True, encoding="gbk", errors="ignore" ) for line in ipconfig.split("\n"): if "IPv4" in line and ("192.168" in line or "10." in line): ip = line.split(":")[1].strip() return ".".join(ip.split(".")[:3]) + "." except: pass return "192.168.1." # 修复:正确查询MAC厂商 def get_vendor(mac): try: url = MAC_API + mac.replace("-", ":") r = requests.get(url, timeout=1.5) if r.status_code == 200 and r.text.strip(): return r.text.strip() return "未知厂商" except: return "查询失败" def ip_to_int(ip): parts = list(map(int, ip.split("."))) return parts[0] << 24 | parts[1] << 16 | parts[2] << 8 | parts[3] # 修复进度条更新(不用lambda赋值) def update_progress(val): progress_bar["value"] = val progress_label.config(text=f"进度:{val}%") def scan_thread(): subnet = get_subnet() # 清空列表 root.after(0, lambda: tree.delete(*tree.get_children())) root.after(0, lambda: status_main.config(text="开始扫描...")) root.after(0, update_progress, 0) total = 254 for idx in range(1, total + 1): current_ip = subnet + str(idx) # 刷新当前扫描IP root.after(0, lambda ip=current_ip: status_ip.config(text=f"正在扫描:{ip}")) subprocess.Popen( f"ping -n 1 -w 100 {current_ip}", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) per = int(idx / total * 100) root.after(0, update_progress, per) time.sleep(0.015) root.after(0, lambda: status_ip.config(text="正在整理并排序设备...")) time.sleep(1.2) # 读取系统ARP表 try: arp_out = subprocess.check_output( "arp -a", shell=True, text=True, encoding="gbk", errors="ignore" ) except: arp_out = "" pattern = r"(\d+\.\d+\.\d+\.\d+)\s+([\da-fA-F:-]+)" matches = re.findall(pattern, arp_out) device_list = [] for ip, mac in matches: if "ff-ff-ff" in mac or "00-00-00" in mac: continue if not (ip.startswith("192.168") or ip.startswith("10.")): continue vendor = get_vendor(mac) device_list.append((ip, mac, vendor)) # IP升序排序 device_list.sort(key=lambda x: ip_to_int(x[0])) # 插入表格 count = 0 for ip, mac, vendor in device_list: root.after(0, lambda i=ip, m=mac, v=vendor: tree.insert("", "end", values=(i, m, v))) count += 1 root.after(0, update_progress, 100) root.after(0, lambda: status_main.config(text=f"扫描完成,共发现 {count} 台设备")) root.after(0, lambda: status_ip.config(text="空闲")) root.after(0, lambda: scan_btn.config(state=tk.NORMAL)) def start_scan(): scan_btn.config(state=tk.DISABLED) threading.Thread(target=scan_thread, daemon=True).start() def show_nic_info(): try: nic = subprocess.check_output( "wmic nic get Name,Manufacturer", shell=True, text=True, encoding="gbk", errors="ignore" ) win = tk.Toplevel(root) win.title("本机网卡信息") win.geometry("650x450") txt = scrolledtext.ScrolledText(win, width=80, height=22) txt.pack(padx=10, pady=10, fill=tk.BOTH, expand=True) txt.insert(tk.END, nic) except: messagebox.showerror("错误", "无法获取网卡信息") # ==================== GUI界面 ==================== root = tk.Tk() root.title("局域网 IP/MAC/厂商 扫描器 最终修复版") root.geometry("780x580") title_label = ttk.Label(root, text="局域网扫描工具(进度条+实时IP+厂商查询+IP排序)", font=("微软雅黑", 14, "bold")) title_label.pack(pady=10) btn_frame = ttk.Frame(root) btn_frame.pack(pady=5) scan_btn = ttk.Button(btn_frame, text="开始扫描", command=start_scan) scan_btn.grid(row=0, column=0, padx=10) nic_btn = ttk.Button(btn_frame, text="本机网卡信息", command=show_nic_info) nic_btn.grid(row=0, column=1, padx=10) status_main = ttk.Label(root, text="就绪", font=("微软雅黑", 10)) status_main.pack(pady=2) columns = ("ip", "mac", "vendor") tree = ttk.Treeview(root, columns=columns, show="headings") tree.heading("ip", text="IP地址") tree.heading("mac", text="MAC地址") tree.heading("vendor", text="网卡厂商") tree.column("ip", width=220) tree.column("mac", width=280) tree.column("vendor", width=240) tree.pack(padx=20, pady=10, fill=tk.BOTH, expand=True) # 底部实时IP状态栏 status_ip = ttk.Label(root, text="空闲", font=("微软雅黑", 9), foreground="#0066cc") status_ip.pack(fill=tk.X, padx=15) # 进度条区域 progress_frame = ttk.Frame(root) progress_frame.pack(fill=tk.X, padx=20, pady=8) progress_bar = ttk.Progressbar(progress_frame, orient=tk.HORIZONTAL, mode='determinate') progress_bar.pack(side=tk.LEFT, fill=tk.X, expand=True) progress_label = ttk.Label(progress_frame, text="进度:0%", width=12) progress_label.pack(side=tk.RIGHT) root.mainloop()