使用 Python 通过 ISAPI 读取海康威视摄像头设备信息

海康威视(Hikvision)摄像头提供了一套基于 HTTP 的 ISAPI(Intelligent Security API)接口,可以方便地通过程序读取设备信息、配置参数等。本文介绍如何用 Python 通过 ISAPI 接口读取海康摄像头的设备信息。

ISAPI 简介

ISAPI 是海康威视定义的一套 RESTful 风格接口,运行在摄像头的 Web 服务(默认端口 80/443)上。接口路径通常以 /ISAPI/ 开头,请求和响应使用 XML 格式。常见的设备信息接口包括:

接口路径说明
/ISAPI/System/deviceInfo获取设备基本信息(型号、序列号、固件版本等)
/ISAPI/System/status获取设备运行状态(在线时间、CPU/内存使用率等)
/ISAPI/System/Network/interfaces获取网络接口信息(IP、MAC 等)

认证方式

海康摄像头支持两种 HTTP 认证方式:

  • HTTP Basic Auth:部分设备或旧固件使用
  • HTTP Digest Auth:推荐方式,更安全

实际对接中,通常先尝试 Basic Auth,如果返回 401 再降级到 Digest Auth。Python 的 requests 库对两种方式都有良好支持。

实现代码

依赖安装

pip install requests xmltodict

读取单台设备信息

核心思路很简单:构造 ISAPI URL,使用 HTTP Digest 认证发起 GET 请求,解析返回的 XML:

import logging
from ipaddress import ip_address
from requests.auth import HTTPDigestAuth
import requests
import xmltodict

logger = logging.getLogger(__name__)

def get_camera_info(ip, port=80, username="admin", password="your_password") -> dict:
    """通过 ISAPI 读取海康摄像头设备信息"""
    if not isinstance(ip_address(ip), ip_address):
        logger.error("%s 不是合法的 IP 地址", ip)
        return {}

    url = f"http://{ip}:{port}/ISAPI/System/deviceInfo"
    try:
        resp = requests.get(
            url,
            auth=HTTPDigestAuth(username, password),
            timeout=3,
            verify=False,
            allow_redirects=True,
        )
        resp.raise_for_status()
        dev_info = xmltodict.parse(resp.text).get("DeviceInfo", {})
        dev_info["ip"] = str(ip)
        return dev_info
    except Exception as e:
        logger.error("连接 %s 失败: %s", ip, e)
        return {}

调用示例:

info = get_camera_info("192.168.1.64", password="camera_password")
print(info)

返回的数据大致如下(已转为 Python 字典):

{
  "model": "DS-2CD3T47G2-LU",
  "deviceName": "Camera-01",
  "deviceSerialNumber": "DS-2CD3T47G2-LU20230801AACH12345",
  "macAddress": "A0:BD:1D:XX:XX:XX",
  "firmwareVersion": "V5.7.15",
  "encoderVersion": "V7.1",
  "encoderReleasedDate": "2023-08-01",
  "releaseDate": "2023-08-01",
  "deviceType": "IPC",
  "telecontrolID": "023",
  "supportBeep": "false",
  "supportLED": "true",
  "ip": "192.168.1.64"
}

批量扫描网段

如果需要扫描整个网段中的所有海康摄像头,可以遍历 IP 段并逐一调用:

from ipaddress import ip_network

def scan_cameras(network, port=80, username="admin", password="your_password"):
    """扫描网段内所有海康摄像头"""
    net = ip_network(network, strict=False)
    cameras = []
    for ip in net.hosts():
        print(f"正在扫描 {ip}...")
        info = get_camera_info(str(ip), port, username, password)
        if info:
            cameras.append(info)
            print(f"  -> 发现设备: {info.get('model')} ({info.get('deviceName')})")
    return cameras

调用示例:

cameras = scan_cameras("192.168.1.0/24", password="camera_password")
print(f"共发现 {len(cameras)} 台设备")
for cam in cameras:
    print(f"  {cam['ip']} - {cam['model']} - SN: {cam.get('deviceSerialNumber')}")

封装为可复用的客户端类

如果需要频繁调用不同的 ISAPI 接口,可以封装一个客户端类,自动处理认证和会话复用:

from urllib.parse import urljoin
from requests.auth import HTTPBasicAuth, HTTPDigestAuth

class HikvisionClient:
    def __init__(self, host, username="admin", password="password", timeout=3):
        self.host = host.rstrip("/")
        self.username = username
        self.password = password
        self.timeout = timeout
        self.session = self._init_session()

    def _init_session(self):
        """初始化会话,自动选择认证方式"""
        url = f"{self.host}/ISAPI/System/status"
        session = requests.session()
        session.auth = HTTPBasicAuth(self.username, self.password)
        resp = session.get(url, verify=False, allow_redirects=True, timeout=self.timeout)
        if resp.status_code == 401:
            session.auth = HTTPDigestAuth(self.username, self.password)
            resp = session.get(url, verify=False, allow_redirects=True, timeout=self.timeout)
        resp.raise_for_status()
        return session

    def get(self, path):
        """调用 ISAPI GET 接口,返回解析后的字典"""
        full_url = f"{self.host}/ISAPI/{path}"
        resp = self.session.get(
            full_url, verify=False, allow_redirects=True, timeout=self.timeout
        )
        resp.raise_for_status()
        return xmltodict.parse(resp.text)

# 使用示例
client = HikvisionClient("http://192.168.1.64", password="camera_password")

# 读取设备信息
device_info = client.get("System/deviceInfo")
print(device_info)

# 读取网络接口信息
network_info = client.get("System/Network/interfaces")
print(network_info)

返回数据说明

/ISAPI/System/deviceInfo 接口返回的关键字段:

字段说明
model设备型号
deviceName设备名称(用户可自定义)
deviceSerialNumber设备序列号(唯一标识)
macAddressMAC 地址
firmwareVersion固件版本号
releaseDate固件发布日期
deviceType设备类型(IPC/NVR/DVR 等)

注意事项

  1. HTTPS 证书:测试环境中摄像头通常使用自签名证书,代码中 verify=False 会跳过证书验证,生产环境建议配置正规证书
  2. 认证失败:默认密码已修改的设备会返回 401,建议先确认认证凭据
  3. 超时设置:扫描网段时建议设置较短的超时时间(3 秒),避免长时间等待离线设备
  4. 频率限制:大量扫描时建议加入并发控制和延时,避免对网络造成压力
  5. XML 解析xmltodict 会将 XML 转为 Python 字典,嵌套结构用点号或字典访问

小结

通过海康 ISAPI 接口,几行 Python 代码就能读取摄像头设备信息。核心就是 HTTP + Digest Auth + XML 解析三个要素。将设备信息读取与 NetBox、CMDB 等资产管理系统结合,可以实现摄像头资产的自动化管理和定期巡检。

参考:海康威视 ISAPI 开发指南