如何用Python识别本机及网络接入的客户端机器类型?
嘿,这个问题我刚好折腾过几次,来给你捋捋可行的方案:
要识别接入局域网的客户端设备类型,核心是抓设备的网络特征——要么是硬件层面的MAC地址(溯源厂商),要么是软件层面的服务/应用标识,或者是客户端主动发送的请求头信息。下面是几个实用的实现方法:
方法一:ARP扫描+MAC厂商识别(最基础的设备类型判断)
局域网里的设备要通信都会用到ARP协议,我们可以发送ARP广播请求,收集响应设备的IP和MAC地址,然后通过MAC的前6位(OUI,组织唯一标识符)匹配对应的厂商,就能大致判断设备类型(比如苹果手机、小米路由器、惠普打印机这类)。
用Python的scapy库就能轻松实现,先安装依赖:pip install scapy,然后看示例代码:
from scapy.all import ARP, Ether, srp # 替换成你的局域网网段,比如192.168.0.0/24 target_ip = "192.168.1.0/24" # 构造ARP请求包 arp = ARP(pdst=target_ip) # 构造以太网广播帧 ether = Ether(dst="ff:ff:ff:ff:ff:ff") # 组合数据包 packet = ether / arp # 发送包并等待响应,超时3秒 result = srp(packet, timeout=3, verbose=0)[0] # 解析响应,收集客户端IP和MAC clients = [] for sent, received in result: clients.append({"ip": received.psrc, "mac": received.hwsrc}) # 这里可以用完整的OUI数据库来匹配厂商,我这里做个简单示例 # 实际使用可以去IEEE官网下载完整的OUI列表,存成本地CSV/JSON来匹配 oui_vendor_map = { "00:1A:2B": "Apple Inc.", "5C:51:4F": "Xiaomi Communications", "00:E0:4C": "Realtek Semiconductor", "00:1E:0B": "Hewlett-Packard (HP)" } print("局域网客户端设备信息:") for client in clients: # 提取MAC的前8位(OUI部分,格式XX:XX:XX) oui = client["mac"][:8].upper() vendor = oui_vendor_map.get(oui, "未知厂商") print(f"IP: {client['ip']} | MAC: {client['mac']} | 厂商/设备类型: {vendor}")
这个方法的优势是不需要客户端主动配合,只要设备在局域网内联网就能扫到,缺点是只能判断厂商,没法区分具体是手机还是平板(比如苹果的OUI都是一样的)。
方法二:针对Web客户端——解析HTTP User-Agent
如果你的Python程序是个Web服务,客户端是浏览器、APP这类Web客户端,那可以直接读取请求头里的User-Agent字段,解析这个字符串就能精准判断设备类型(移动端、PC、平板,甚至具体的操作系统和浏览器)。
可以用user-agents库来简化解析,先安装:pip install user-agents,Flask服务的示例代码:
from flask import Flask, request from user_agents import parse app = Flask(__name__) @app.route("/") def detect_client(): # 获取请求头里的User-Agent ua_string = request.headers.get("User-Agent", "") ua_info = parse(ua_string) # 判断设备类型 device_type = "未知设备" if ua_info.is_mobile: device_type = "手机" elif ua_info.is_tablet: device_type = "平板" elif ua_info.is_pc: device_type = "桌面电脑" elif ua_info.is_bot: device_type = "爬虫/机器人" return ( f"客户端设备类型: {device_type}\n" f"操作系统: {ua_info.os.family} {ua_info.os.version_string}\n" f"浏览器: {ua_info.browser.family} {ua_info.browser.version_string}" ) if __name__ == "__main__": # 监听所有网卡,方便局域网内客户端访问 app.run(host="0.0.0.0", port=5000)
这个方法的局限性是只能识别主动访问你Web服务的客户端,而且User-Agent可以被伪造,准确性依赖客户端的真实标识。
方法三:端口扫描+服务特征识别(更精准的设备类型)
有些设备有专属的开放端口和服务,比如打印机通常开9100端口,IP摄像头可能开8080或专属IPC端口,路由器可能开22(SSH)、80(Web管理)端口。我们可以用Python调用nmap来扫描客户端的开放端口,根据服务特征判断设备类型。
先安装依赖:pip install python-nmap,同时要确保你的系统里安装了nmap工具(Windows可以去官网下载,Linux用apt install nmap)。示例代码:
import nmap # 初始化nmap扫描器 nm = nmap.PortScanner() # 替换成要扫描的客户端IP,扫描1-1000常用端口 target_host = "192.168.1.100" nm.scan(target_host, "1-1000") print(f"扫描目标: {target_host}") print(f"设备状态: {nm[target_host].state()}") for proto in nm[target_host].all_protocols(): print(f"\n协议: {proto}") ports = nm[target_host][proto].keys() for port in ports: service = nm[target_host][proto][port]["name"] product = nm[target_host][proto][port].get("product", "") version = nm[target_host][proto][port].get("version", "") print(f"端口: {port} | 服务: {service} | 产品: {product} {version}") # 根据服务特征判断设备类型 if service == "ipp" or port == 9100: print("→ 这可能是一台打印机") elif service == "http" and "camera" in product.lower(): print("→ 这可能是一台IP摄像头") elif service == "ssh" and product == "OpenWrt": print("→ 这可能是一台运行OpenWrt的路由器")
这个方法能识别更具体的设备,但需要较高的权限(Linux下要sudo),而且容易被客户端防火墙拦截,导致扫描不到端口。
- 局域网扫描需要程序有足够权限:Windows下要以管理员身份运行,Linux下加sudo。
- 部分设备可能禁用ARP响应或开启防火墙,会导致扫描不到。
- User-Agent可以被伪造,做精准判断时要结合其他特征。
内容的提问来源于stack exchange,提问作者s1gnific4nt

