<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Python on HiDa</title><link>https://www.0niu.cn/tags/python/</link><description>Recent content in Python on HiDa</description><generator>Hugo -- gohugo.io</generator><language>zh</language><lastBuildDate>Sun, 25 May 2025 22:42:39 +0800</lastBuildDate><atom:link href="https://www.0niu.cn/tags/python/index.xml" rel="self" type="application/rss+xml"/><item><title>使用 Python 通过 ISAPI 读取海康威视摄像头设备信息</title><link>https://www.0niu.cn/posts/hikvision-isapi-read-device-info-python/</link><pubDate>Sun, 25 May 2025 22:42:39 +0800</pubDate><guid>https://www.0niu.cn/posts/hikvision-isapi-read-device-info-python/</guid><description>&lt;p>海康威视（Hikvision）摄像头提供了一套基于 HTTP 的 ISAPI（Intelligent Security API）接口，可以方便地通过程序读取设备信息、配置参数等。本文介绍如何用 Python 通过 ISAPI 接口读取海康摄像头的设备信息。&lt;/p>
&lt;h2 id="isapi-简介">ISAPI 简介&lt;/h2>
&lt;p>ISAPI 是海康威视定义的一套 RESTful 风格接口，运行在摄像头的 Web 服务（默认端口 80/443）上。接口路径通常以 &lt;code>/ISAPI/&lt;/code> 开头，请求和响应使用 XML 格式。常见的设备信息接口包括：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>接口路径&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>/ISAPI/System/deviceInfo&lt;/code>&lt;/td>
&lt;td>获取设备基本信息（型号、序列号、固件版本等）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>/ISAPI/System/status&lt;/code>&lt;/td>
&lt;td>获取设备运行状态（在线时间、CPU/内存使用率等）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>/ISAPI/System/Network/interfaces&lt;/code>&lt;/td>
&lt;td>获取网络接口信息（IP、MAC 等）&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table></description><content>&lt;p>海康威视（Hikvision）摄像头提供了一套基于 HTTP 的 ISAPI（Intelligent Security API）接口，可以方便地通过程序读取设备信息、配置参数等。本文介绍如何用 Python 通过 ISAPI 接口读取海康摄像头的设备信息。&lt;/p>
&lt;h2 id="isapi-简介">ISAPI 简介&lt;/h2>
&lt;p>ISAPI 是海康威视定义的一套 RESTful 风格接口，运行在摄像头的 Web 服务（默认端口 80/443）上。接口路径通常以 &lt;code>/ISAPI/&lt;/code> 开头，请求和响应使用 XML 格式。常见的设备信息接口包括：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>接口路径&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>/ISAPI/System/deviceInfo&lt;/code>&lt;/td>
&lt;td>获取设备基本信息（型号、序列号、固件版本等）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>/ISAPI/System/status&lt;/code>&lt;/td>
&lt;td>获取设备运行状态（在线时间、CPU/内存使用率等）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>/ISAPI/System/Network/interfaces&lt;/code>&lt;/td>
&lt;td>获取网络接口信息（IP、MAC 等）&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="认证方式">认证方式&lt;/h2>
&lt;p>海康摄像头支持两种 HTTP 认证方式：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>HTTP Basic Auth&lt;/strong>：部分设备或旧固件使用&lt;/li>
&lt;li>&lt;strong>HTTP Digest Auth&lt;/strong>：推荐方式，更安全&lt;/li>
&lt;/ul>
&lt;p>实际对接中，通常先尝试 Basic Auth，如果返回 401 再降级到 Digest Auth。Python 的 &lt;code>requests&lt;/code> 库对两种方式都有良好支持。&lt;/p>
&lt;h2 id="实现代码">实现代码&lt;/h2>
&lt;h3 id="依赖安装">依赖安装&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>pip install requests xmltodict
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="读取单台设备信息">读取单台设备信息&lt;/h3>
&lt;p>核心思路很简单：构造 ISAPI URL，使用 HTTP Digest 认证发起 GET 请求，解析返回的 XML：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> logging
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">from&lt;/span> ipaddress &lt;span style="color:#f92672">import&lt;/span> ip_address
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">from&lt;/span> requests.auth &lt;span style="color:#f92672">import&lt;/span> HTTPDigestAuth
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> requests
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> xmltodict
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>logger &lt;span style="color:#f92672">=&lt;/span> logging&lt;span style="color:#f92672">.&lt;/span>getLogger(__name__)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">get_camera_info&lt;/span>(ip, port&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">80&lt;/span>, username&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;admin&amp;#34;&lt;/span>, password&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;your_password&amp;#34;&lt;/span>) &lt;span style="color:#f92672">-&amp;gt;&lt;/span> dict:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&amp;#34;通过 ISAPI 读取海康摄像头设备信息&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">not&lt;/span> isinstance(ip_address(ip), ip_address):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logger&lt;span style="color:#f92672">.&lt;/span>error(&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">%s&lt;/span>&lt;span style="color:#e6db74"> 不是合法的 IP 地址&amp;#34;&lt;/span>, ip)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> url &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;http://&lt;/span>&lt;span style="color:#e6db74">{&lt;/span>ip&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">:&lt;/span>&lt;span style="color:#e6db74">{&lt;/span>port&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/ISAPI/System/deviceInfo&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">try&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> resp &lt;span style="color:#f92672">=&lt;/span> requests&lt;span style="color:#f92672">.&lt;/span>get(
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> url,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> auth&lt;span style="color:#f92672">=&lt;/span>HTTPDigestAuth(username, password),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> timeout&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">3&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> verify&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">False&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> allow_redirects&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">True&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> )
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> resp&lt;span style="color:#f92672">.&lt;/span>raise_for_status()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> dev_info &lt;span style="color:#f92672">=&lt;/span> xmltodict&lt;span style="color:#f92672">.&lt;/span>parse(resp&lt;span style="color:#f92672">.&lt;/span>text)&lt;span style="color:#f92672">.&lt;/span>get(&lt;span style="color:#e6db74">&amp;#34;DeviceInfo&amp;#34;&lt;/span>, {})
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> dev_info[&lt;span style="color:#e6db74">&amp;#34;ip&amp;#34;&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> str(ip)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> dev_info
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">except&lt;/span> &lt;span style="color:#a6e22e">Exception&lt;/span> &lt;span style="color:#66d9ef">as&lt;/span> e:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logger&lt;span style="color:#f92672">.&lt;/span>error(&lt;span style="color:#e6db74">&amp;#34;连接 &lt;/span>&lt;span style="color:#e6db74">%s&lt;/span>&lt;span style="color:#e6db74"> 失败: &lt;/span>&lt;span style="color:#e6db74">%s&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>, ip, e)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> {}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>调用示例：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>info &lt;span style="color:#f92672">=&lt;/span> get_camera_info(&lt;span style="color:#e6db74">&amp;#34;192.168.1.64&amp;#34;&lt;/span>, password&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;camera_password&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>print(info)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>返回的数据大致如下（已转为 Python 字典）：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;model&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;DS-2CD3T47G2-LU&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;deviceName&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;Camera-01&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;deviceSerialNumber&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;DS-2CD3T47G2-LU20230801AACH12345&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;macAddress&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;A0:BD:1D:XX:XX:XX&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;firmwareVersion&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;V5.7.15&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;encoderVersion&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;V7.1&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;encoderReleasedDate&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;2023-08-01&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;releaseDate&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;2023-08-01&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;deviceType&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;IPC&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;telecontrolID&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;023&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;supportBeep&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;false&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;supportLED&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;true&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;ip&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;192.168.1.64&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="批量扫描网段">批量扫描网段&lt;/h3>
&lt;p>如果需要扫描整个网段中的所有海康摄像头，可以遍历 IP 段并逐一调用：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">from&lt;/span> ipaddress &lt;span style="color:#f92672">import&lt;/span> ip_network
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">scan_cameras&lt;/span>(network, port&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">80&lt;/span>, username&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;admin&amp;#34;&lt;/span>, password&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;your_password&amp;#34;&lt;/span>):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&amp;#34;扫描网段内所有海康摄像头&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> net &lt;span style="color:#f92672">=&lt;/span> ip_network(network, strict&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">False&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cameras &lt;span style="color:#f92672">=&lt;/span> []
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> ip &lt;span style="color:#f92672">in&lt;/span> net&lt;span style="color:#f92672">.&lt;/span>hosts():
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> print(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;正在扫描 &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>ip&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">...&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> info &lt;span style="color:#f92672">=&lt;/span> get_camera_info(str(ip), port, username, password)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> info:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cameras&lt;span style="color:#f92672">.&lt;/span>append(info)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> print(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34; -&amp;gt; 发现设备: &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>info&lt;span style="color:#f92672">.&lt;/span>get(&lt;span style="color:#e6db74">&amp;#39;model&amp;#39;&lt;/span>)&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> (&lt;/span>&lt;span style="color:#e6db74">{&lt;/span>info&lt;span style="color:#f92672">.&lt;/span>get(&lt;span style="color:#e6db74">&amp;#39;deviceName&amp;#39;&lt;/span>)&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">)&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> cameras
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>调用示例：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>cameras &lt;span style="color:#f92672">=&lt;/span> scan_cameras(&lt;span style="color:#e6db74">&amp;#34;192.168.1.0/24&amp;#34;&lt;/span>, password&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;camera_password&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>print(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;共发现 &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>len(cameras)&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> 台设备&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">for&lt;/span> cam &lt;span style="color:#f92672">in&lt;/span> cameras:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> print(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34; &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>cam[&lt;span style="color:#e6db74">&amp;#39;ip&amp;#39;&lt;/span>]&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> - &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>cam[&lt;span style="color:#e6db74">&amp;#39;model&amp;#39;&lt;/span>]&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> - SN: &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>cam&lt;span style="color:#f92672">.&lt;/span>get(&lt;span style="color:#e6db74">&amp;#39;deviceSerialNumber&amp;#39;&lt;/span>)&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="封装为可复用的客户端类">封装为可复用的客户端类&lt;/h3>
&lt;p>如果需要频繁调用不同的 ISAPI 接口，可以封装一个客户端类，自动处理认证和会话复用：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">from&lt;/span> urllib.parse &lt;span style="color:#f92672">import&lt;/span> urljoin
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">from&lt;/span> requests.auth &lt;span style="color:#f92672">import&lt;/span> HTTPBasicAuth, HTTPDigestAuth
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">HikvisionClient&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> __init__(self, host, username&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;admin&amp;#34;&lt;/span>, password&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;password&amp;#34;&lt;/span>, timeout&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">3&lt;/span>):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> self&lt;span style="color:#f92672">.&lt;/span>host &lt;span style="color:#f92672">=&lt;/span> host&lt;span style="color:#f92672">.&lt;/span>rstrip(&lt;span style="color:#e6db74">&amp;#34;/&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> self&lt;span style="color:#f92672">.&lt;/span>username &lt;span style="color:#f92672">=&lt;/span> username
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> self&lt;span style="color:#f92672">.&lt;/span>password &lt;span style="color:#f92672">=&lt;/span> password
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> self&lt;span style="color:#f92672">.&lt;/span>timeout &lt;span style="color:#f92672">=&lt;/span> timeout
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> self&lt;span style="color:#f92672">.&lt;/span>session &lt;span style="color:#f92672">=&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>_init_session()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">_init_session&lt;/span>(self):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&amp;#34;初始化会话，自动选择认证方式&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> url &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">{&lt;/span>self&lt;span style="color:#f92672">.&lt;/span>host&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/ISAPI/System/status&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> session &lt;span style="color:#f92672">=&lt;/span> requests&lt;span style="color:#f92672">.&lt;/span>session()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> session&lt;span style="color:#f92672">.&lt;/span>auth &lt;span style="color:#f92672">=&lt;/span> HTTPBasicAuth(self&lt;span style="color:#f92672">.&lt;/span>username, self&lt;span style="color:#f92672">.&lt;/span>password)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> resp &lt;span style="color:#f92672">=&lt;/span> session&lt;span style="color:#f92672">.&lt;/span>get(url, verify&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">False&lt;/span>, allow_redirects&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">True&lt;/span>, timeout&lt;span style="color:#f92672">=&lt;/span>self&lt;span style="color:#f92672">.&lt;/span>timeout)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> resp&lt;span style="color:#f92672">.&lt;/span>status_code &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">401&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> session&lt;span style="color:#f92672">.&lt;/span>auth &lt;span style="color:#f92672">=&lt;/span> HTTPDigestAuth(self&lt;span style="color:#f92672">.&lt;/span>username, self&lt;span style="color:#f92672">.&lt;/span>password)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> resp &lt;span style="color:#f92672">=&lt;/span> session&lt;span style="color:#f92672">.&lt;/span>get(url, verify&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">False&lt;/span>, allow_redirects&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">True&lt;/span>, timeout&lt;span style="color:#f92672">=&lt;/span>self&lt;span style="color:#f92672">.&lt;/span>timeout)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> resp&lt;span style="color:#f92672">.&lt;/span>raise_for_status()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> session
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">get&lt;/span>(self, path):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&amp;#34;调用 ISAPI GET 接口，返回解析后的字典&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> full_url &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">{&lt;/span>self&lt;span style="color:#f92672">.&lt;/span>host&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/ISAPI/&lt;/span>&lt;span style="color:#e6db74">{&lt;/span>path&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> resp &lt;span style="color:#f92672">=&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>session&lt;span style="color:#f92672">.&lt;/span>get(
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> full_url, verify&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">False&lt;/span>, allow_redirects&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">True&lt;/span>, timeout&lt;span style="color:#f92672">=&lt;/span>self&lt;span style="color:#f92672">.&lt;/span>timeout
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> )
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> resp&lt;span style="color:#f92672">.&lt;/span>raise_for_status()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> xmltodict&lt;span style="color:#f92672">.&lt;/span>parse(resp&lt;span style="color:#f92672">.&lt;/span>text)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 使用示例&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>client &lt;span style="color:#f92672">=&lt;/span> HikvisionClient(&lt;span style="color:#e6db74">&amp;#34;http://192.168.1.64&amp;#34;&lt;/span>, password&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;camera_password&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 读取设备信息&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>device_info &lt;span style="color:#f92672">=&lt;/span> client&lt;span style="color:#f92672">.&lt;/span>get(&lt;span style="color:#e6db74">&amp;#34;System/deviceInfo&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>print(device_info)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 读取网络接口信息&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>network_info &lt;span style="color:#f92672">=&lt;/span> client&lt;span style="color:#f92672">.&lt;/span>get(&lt;span style="color:#e6db74">&amp;#34;System/Network/interfaces&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>print(network_info)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="返回数据说明">返回数据说明&lt;/h2>
&lt;p>&lt;code>/ISAPI/System/deviceInfo&lt;/code> 接口返回的关键字段：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>字段&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>model&lt;/code>&lt;/td>
&lt;td>设备型号&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>deviceName&lt;/code>&lt;/td>
&lt;td>设备名称（用户可自定义）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>deviceSerialNumber&lt;/code>&lt;/td>
&lt;td>设备序列号（唯一标识）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>macAddress&lt;/code>&lt;/td>
&lt;td>MAC 地址&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>firmwareVersion&lt;/code>&lt;/td>
&lt;td>固件版本号&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>releaseDate&lt;/code>&lt;/td>
&lt;td>固件发布日期&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>deviceType&lt;/code>&lt;/td>
&lt;td>设备类型（IPC/NVR/DVR 等）&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="注意事项">注意事项&lt;/h2>
&lt;ol>
&lt;li>&lt;strong>HTTPS 证书&lt;/strong>：测试环境中摄像头通常使用自签名证书，代码中 &lt;code>verify=False&lt;/code> 会跳过证书验证，生产环境建议配置正规证书&lt;/li>
&lt;li>&lt;strong>认证失败&lt;/strong>：默认密码已修改的设备会返回 401，建议先确认认证凭据&lt;/li>
&lt;li>&lt;strong>超时设置&lt;/strong>：扫描网段时建议设置较短的超时时间（3 秒），避免长时间等待离线设备&lt;/li>
&lt;li>&lt;strong>频率限制&lt;/strong>：大量扫描时建议加入并发控制和延时，避免对网络造成压力&lt;/li>
&lt;li>&lt;strong>XML 解析&lt;/strong>：&lt;code>xmltodict&lt;/code> 会将 XML 转为 Python 字典，嵌套结构用点号或字典访问&lt;/li>
&lt;/ol>
&lt;h2 id="小结">小结&lt;/h2>
&lt;p>通过海康 ISAPI 接口，几行 Python 代码就能读取摄像头设备信息。核心就是 HTTP + Digest Auth + XML 解析三个要素。将设备信息读取与 NetBox、CMDB 等资产管理系统结合，可以实现摄像头资产的自动化管理和定期巡检。&lt;/p>
&lt;blockquote>
&lt;p>参考：海康威视 &lt;a href="https://open.hikvision.com/">ISAPI 开发指南&lt;/a>&lt;/p>
&lt;/blockquote></content></item></channel></rss>