当前位置: 首页 > news >正文

AppAgent 源码 (xml 解析)

1. 数据准备

adb shell uiautomator dump /sdcard/output.xml  # 获取手机ui界面的xml文件
adb pull /sdcard/output.xml output.xml		# 将手机上的xml文件拉取到电脑上

具体的xml文件:

<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<hierarchy rotation="0"><node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1220,2712]"><node index="0" text="" resource-id="" class="android.widget.LinearLayout" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1220,2712]"><node index="0" text="" resource-id="android:id/content" class="android.widget.FrameLayout" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1220,2712]"><node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1220,2712]"><node index="0" text="" resource-id="com.miui.home:id/shortcut_menu_layer" class="android.widget.FrameLayout" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1220,2712]"><node index="0" text="" resource-id="com.miui.home:id/drag_layer_background" class="android.view.View" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1220,2712]" /><node index="1" text="" resource-id="com.miui.home:id/drag_layer" class="android.widget.FrameLayout" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1220,2712]"><node index="0" text="" resource-id="com.miui.home:id/shortcut_menu_blur_view" class="android.view.View" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1220,2712]" /><node index="1" text="" resource-id="com.miui.home:id/drag_view_container" class="android.widget.FrameLayout" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1220,2712]" /><node index="2" text="" resource-id="com.miui.home:id/screen" class="android.widget.FrameLayout" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1220,2712]"><node index="1" text="" resource-id="com.miui.home:id/scrim_view" class="android.view.View" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1220,2712]" /><node index="2" text="" resource-id="com.miui.home:id/screen_content" class="android.widget.FrameLayout" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1220,2712]"><node index="0" text="" resource-id="com.miui.home:id/workspace" class="com.miui.home.launcher.ScreenView" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="true" long-clickable="false" password="false" selected="false" bounds="[0,0][1220,2660]"><node index="1" text="" resource-id="" class="android.widget.FrameLayout" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,1959][1220,2133]"><node index="0" text="" resource-id="" class="com.miui.home.launcher.ScreenView" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="true" long-clickable="false" password="false" selected="false" bounds="[0,1959][1220,2133]"><node index="0" text="" resource-id="" class="android.widget.ImageView" package="com.miui.home" content-desc="App vault" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[451,2019][501,2069]" /><node index="1" text="" resource-id="" class="android.widget.ImageView" package="com.miui.home" content-desc="1 screen" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[504,2019][557,2072]" /><node index="2" text="" resource-id="" class="android.widget.ImageView" package="com.miui.home" content-desc="2 screen" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="true" bounds="[557,2019][610,2072]" /><node index="3" text="" resource-id="" class="android.widget.ImageView" package="com.miui.home" content-desc="3 screen" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[610,2019][663,2072]" /><node index="4" text="" resource-id="" class="android.widget.ImageView" package="com.miui.home" content-desc="4 screen" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[663,2019][716,2072]" /><node index="5" text="" resource-id="" class="android.widget.ImageView" package="com.miui.home" content-desc="5 screen" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[716,2019][769,2072]" /></node></node><node index="2" text="" resource-id="" class="android.widget.FrameLayout" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,243][1220,2660]"><node index="0" text="" resource-id="" class="android.view.ViewGroup" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,243][1220,2660]"><node index="0" text="Amap" resource-id="" class="android.widget.TextView" package="com.miui.home" content-desc="Amap" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="true" password="false" selected="false" bounds="[38,1101][324,1387]" /><node index="1" text="Clock" resource-id="" class="android.widget.TextView" package="com.miui.home" content-desc="Clock" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="true" password="false" selected="false" bounds="[38,1387][324,1673]" /><node index="2" text="Notes" resource-id="" class="android.widget.TextView" package="com.miui.home" content-desc="Notes" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="true" password="false" selected="false" bounds="[896,1387][1182,1673]" /><node index="3" text="Calculator" resource-id="" class="android.widget.TextView" package="com.miui.home" content-desc="Calculator" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="true" password="false" selected="false" bounds="[38,1673][324,1959]" /><node index="4" text="Settings" resource-id="" class="android.widget.TextView" package="com.miui.home" content-desc="Settings" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="true" password="false" selected="false" bounds="[324,1673][610,1959]" /><node index="5" text="Calendar" resource-id="" class="android.widget.TextView" package="com.miui.home" content-desc="Calendar" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="true" password="false" selected="false" bounds="[610,1673][896,1959]" /><node index="6" text="Weather" resource-id="" class="android.widget.TextView" package="com.miui.home" content-desc="Weather" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="true" password="false" selected="false" bounds="[896,1673][1182,1959]" /></node></node></node><node index="1" text="" resource-id="com.miui.home:id/hotseat" class="android.widget.FrameLayout" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,2133][1220,2419]"><node index="0" text="" resource-id="com.miui.home:id/hotseat_content_screen" class="com.miui.home.launcher.ScreenView" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="true" long-clickable="false" password="false" selected="false" bounds="[12,2133][1208,2419]"><node index="0" text="Phone" resource-id="" class="android.widget.TextView" package="com.miui.home" content-desc="Phone" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="true" password="false" selected="false" bounds="[38,2133][324,2419]" /><node index="1" text="Messaging" resource-id="" class="android.widget.TextView" package="com.miui.home" content-desc="Messaging" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="true" password="false" selected="false" bounds="[324,2133][610,2419]" /><node index="2" text="Camera" resource-id="" class="android.widget.TextView" package="com.miui.home" content-desc="Camera" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="true" password="false" selected="false" bounds="[610,2133][896,2419]" /><node index="3" text="夸克" resource-id="" class="android.widget.TextView" package="com.miui.home" content-desc="夸克" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="true" password="false" selected="false" bounds="[896,2133][1182,2419]" /></node></node></node><node index="3" text="" resource-id="" class="android.widget.FrameLayout" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1220,2712]" /><node index="4" text="" resource-id="com.miui.home:id/search_bar_container" class="android.widget.FrameLayout" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,2418][1220,2712]"><node index="0" text="" resource-id="com.miui.home:id/search_bar" class="android.widget.FrameLayout" package="com.miui.home" content-desc="Search bar" checkable="false" checked="false" clickable="false" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[91,2418][1129,2611]"><node index="0" text="" resource-id="com.miui.home:id/search_bar_desktop_layout" class="android.widget.RelativeLayout" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="true" password="false" selected="false" bounds="[91,2446][1129,2583]"><node index="0" text="" resource-id="com.miui.home:id/search_bar_extra_layout" class="android.widget.ViewAnimator" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[91,2446][1129,2583]"><node index="0" text="" resource-id="com.miui.home:id/search_bar_xiaoai_layout" class="android.widget.FrameLayout" package="com.miui.home" content-desc="Mi AI" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[976,2446][1129,2583]"><node index="0" text="" resource-id="com.miui.home:id/xiaoai_button" class="android.widget.ImageView" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[1015,2446][1090,2583]" /></node></node><node index="1" text="" resource-id="com.miui.home:id/search_bar_content_icon_layout" class="android.widget.FrameLayout" package="com.miui.home" content-desc="Search" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[91,2446][244,2583]"><node index="0" text="" resource-id="com.miui.home:id/search_bar_content_icon" class="android.widget.ImageView" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[130,2446][205,2583]" /></node></node></node></node></node><node index="3" text="" resource-id="" class="android.widget.FrameLayout" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1,2712]"><node index="0" text="" resource-id="com.miui.home:id/default_position" class="android.widget.FrameLayout" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="true" focused="true" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,90][1,2712]" /></node><node index="4" text="" resource-id="com.miui.home:id/drop_target_bar" class="android.widget.FrameLayout" package="com.miui.home" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1220,985]" /></node></node></node></node></node></node>
</hierarchy>

原始的xml文件没有格式化,可以通过这个网址将其格式化,方便阅读:
https://tool.12333si.com/xmlformat/

2. xml 数据解析

1. 导入必要的库

首先,我们需要导入 xml.etree.ElementTree 模块来解析 XML 文件,并使用 dataclasses 模块来定义数据结构。

import xml.etree.ElementTree as ET
from dataclasses import dataclass, field

2. 定义 AndroidElement

原始的代码为:

class AndroidElement:def __init__(self, uid, bbox, attrib):self.uid = uidself.bbox = bboxself.attrib = attrib

但是这样不方便打印输出。

我们使用 dataclass 装饰器定义一个 AndroidElement 类,用于存储每个元素的唯一标识符 (uid)、边界框 (bbox) 和属性 (attrib)。

@dataclass
class AndroidElement:uid: strbbox: tupleattrib: dict = field(default_factory=dict)

3. 配置参数

我们定义了一个全局配置字典 configs,其中包含一个最小距离参数 MIN_DIST,用于判断两个元素是否过于接近。

configs = {"MIN_DIST": 30}

4. 获取元素的唯一标识符

get_id_from_element 函数用于生成每个元素的唯一标识符。它根据元素的 resource-idclasscontent-desc 以及元素的宽度和高度来生成标识符。

def get_id_from_element(elem):bounds = elem.attrib["bounds"][1:-1].split("][")x1, y1 = map(int, bounds[0].split(","))x2, y2 = map(int, bounds[1].split(","))elem_w, elem_h = x2 - x1, y2 - y1if "resource-id" in elem.attrib and elem.attrib["resource-id"]:elem_id = elem.attrib["resource-id"].replace(":", ".").replace("/", "_")else:elem_id = f"{elem.attrib['class']}_{elem_w}_{elem_h}"if ("content-desc" in elem.attriband elem.attrib["content-desc"]and len(elem.attrib["content-desc"]) < 20):content_desc = (elem.attrib["content-desc"].replace("/", "_").replace(" ", "").replace(":", "_"))elem_id += f"_{content_desc}"return elem_id

5. 遍历 XML 树

traverse_tree 函数用于遍历 XML 树,并提取符合条件的元素。它会检查每个元素的属性,并根据配置的最小距离参数判断是否将其添加到列表中。

def traverse_tree(xml_path, elem_list, attrib, add_index=False):path = []for event, elem in ET.iterparse(xml_path, ["start", "end"]):if event == "start":path.append(elem)if attrib in elem.attrib and elem.attrib[attrib] == "true":parent_prefix = ""if len(path) > 1:parent_prefix = get_id_from_element(path[-2])bounds = elem.attrib["bounds"][1:-1].split("][")x1, y1 = map(int, bounds[0].split(","))x2, y2 = map(int, bounds[1].split(","))center = (x1 + x2) // 2, (y1 + y2) // 2elem_id = get_id_from_element(elem)if parent_prefix:elem_id = parent_prefix + "_" + elem_idif add_index:elem_id += f"_{elem.attrib['index']}"close = Falsefor e in elem_list:bbox = e.bboxcenter_ = (bbox[0][0] + bbox[1][0]) // 2, (bbox[0][1] + bbox[1][1]) // 2dist = (abs(center[0] - center_[0]) ** 2+ abs(center[1] - center_[1]) ** 2) ** 0.5if dist <= configs["MIN_DIST"]:close = Truebreakif not close:elem_list.append(AndroidElement(elem_id, ((x1, y1), (x2, y2)), attrib))if event == "end":path.pop()

6. 解析 XML 文件并输出结果

最后,我们指定 XML 文件的路径,并调用 traverse_tree 函数来解析文件。解析完成后,我们输出提取的元素列表及其长度。

xml_path = "../output.xml"
clickable_list = []traverse_tree(xml_path, clickable_list, "clickable", True)print(clickable_list)
print(len(clickable_list))

7. 输出结果

运行上述代码后,程序将输出所有可点击元素的列表及其数量。例如:

[AndroidElement(uid='com.miui.home.launcher.ScreenView_1220_174_android.widget.ImageView_50_50_Appvault_0', bbox=((451, 2019), (501, 2069)), attrib='clickable'), AndroidElement(uid='com.miui.home.launcher.ScreenView_1220_174_android.widget.ImageView_53_53_1screen_1', bbox=((504, 2019), (557, 2072)), attrib='clickable'), AndroidElement(uid='com.miui.home.launcher.ScreenView_1220_174_android.widget.ImageView_53_53_2screen_2', bbox=((557, 2019), (610, 2072)), attrib='clickable'), AndroidElement(uid='com.miui.home.launcher.ScreenView_1220_174_android.widget.ImageView_53_53_3screen_3', bbox=((610, 2019), (663, 2072)), attrib='clickable'), AndroidElement(uid='com.miui.home.launcher.ScreenView_1220_174_android.widget.ImageView_53_53_4screen_4', bbox=((663, 2019), (716, 2072)), attrib='clickable'), AndroidElement(uid='com.miui.home.launcher.ScreenView_1220_174_android.widget.ImageView_53_53_5screen_5', bbox=((716, 2019), (769, 2072)), attrib='clickable'), AndroidElement(uid='android.view.ViewGroup_1220_2417_android.widget.TextView_286_286_Amap_0', bbox=((38, 1101), (324, 1387)), attrib='clickable'), AndroidElement(uid='android.view.ViewGroup_1220_2417_android.widget.TextView_286_286_Clock_1', bbox=((38, 1387), (324, 1673)), attrib='clickable'), AndroidElement(uid='android.view.ViewGroup_1220_2417_android.widget.TextView_286_286_Notes_2', bbox=((896, 1387), (1182, 1673)), attrib='clickable'), AndroidElement(uid='android.view.ViewGroup_1220_2417_android.widget.TextView_286_286_Calculator_3', bbox=((38, 1673), (324, 1959)), attrib='clickable'), AndroidElement(uid='android.view.ViewGroup_1220_2417_android.widget.TextView_286_286_Settings_4', bbox=((324, 1673), (610, 1959)), attrib='clickable'), AndroidElement(uid='android.view.ViewGroup_1220_2417_android.widget.TextView_286_286_Calendar_5', bbox=((610, 1673), (896, 1959)), attrib='clickable'), AndroidElement(uid='android.view.ViewGroup_1220_2417_android.widget.TextView_286_286_Weather_6', bbox=((896, 1673), (1182, 1959)), attrib='clickable'), AndroidElement(uid='com.miui.home.id_hotseat_content_screen_android.widget.TextView_286_286_Phone_0', bbox=((38, 2133), (324, 2419)), attrib='clickable'), AndroidElement(uid='com.miui.home.id_hotseat_content_screen_android.widget.TextView_286_286_Messaging_1', bbox=((324, 2133), (610, 2419)), attrib='clickable'), AndroidElement(uid='com.miui.home.id_hotseat_content_screen_android.widget.TextView_286_286_Camera_2', bbox=((610, 2133), (896, 2419)), attrib='clickable'), AndroidElement(uid='com.miui.home.id_hotseat_content_screen_android.widget.TextView_286_286_夸克_3', bbox=((896, 2133), (1182, 2419)), attrib='clickable'), AndroidElement(uid='com.miui.home.id_search_bar_Searchbar_com.miui.home.id_search_bar_desktop_layout_0', bbox=((91, 2446), (1129, 2583)), attrib='clickable'), AndroidElement(uid='com.miui.home.id_search_bar_extra_layout_com.miui.home.id_search_bar_xiaoai_layout_MiAI_0', bbox=((976, 2446), (1129, 2583)), attrib='clickable'), AndroidElement(uid='com.miui.home.id_search_bar_desktop_layout_com.miui.home.id_search_bar_content_icon_layout_Search_1', bbox=((91, 2446), (244, 2583)), attrib='clickable')]
20

相关文章:

AppAgent 源码 (xml 解析)

1. 数据准备 adb shell uiautomator dump /sdcard/output.xml # 获取手机ui界面的xml文件 adb pull /sdcard/output.xml output.xml # 将手机上的xml文件拉取到电脑上具体的xml文件&#xff1a; <?xml version1.0 encodingUTF-8 standaloneyes ?> <hierarchy ro…...

Oracle 11G还有新BUG?ORACLE 表空间迷案!

前段时间遇到一个奇葩的问题&#xff0c;在开了SR和oracle support追踪两周以后才算是有了不算完美的结果&#xff0c;在这里整理出来给大家分享。 1.问题描述 12/13我司某基地MES全厂停线&#xff0c;系统卡死不可用&#xff0c;通知到我排查&#xff0c;查看alert log看到是…...

FreeSwitch中启用WebRTC

在FreeSwitch中启用WebRTC需要进行一系列配置。以下是详细的步骤&#xff1a; 1. 安装必要的依赖&#xff1a; 确保安装了支持WebRTC的依赖库&#xff0c;如libsrtp。 2. 配置SIP Profile&#xff1a; 编辑 conf/sip_profiles/internal.xml 文件&#xff0c;添加或修改以下内…...

力扣矩阵-算法模版总结

lc-73.矩阵置零-(时隔14天)-12.27 思路&#xff1a;(23min22s) 1.直接遍历遇0将行列设0肯定不行&#xff0c;会影响后续判断&#xff0c;题目又要求原地算法&#xff0c;那么进一步考虑是否可以将元素为0&#xff0c;其行列需要设为0的位置给存储下来&#xff0c;最后再遍历根据…...

服务端高并发分布式结构演进之路

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 服务端高并发分布式结构演进之路 收录于专栏[redis] 本专栏旨在分享学习Redis的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 概述 …...

虚拟机桥接模式

主机Win10,虚拟机xp 1.虚拟机设置中选择桥接模式 2.在虚拟机菜单&#xff1a;编辑>虚拟机网络编辑&#xff0c;点击“更改设置”&#xff0c;可以看到三个网卡&#xff0c;这三个网卡分别对应不同的网络共享模式。桥接模式须使用VMnet0&#xff0c;如果没看到这个网卡&…...

JVM调优实践篇

理论篇 1多功能养鱼塘&#xff0d;JVM内存 大鱼塘O&#xff08;可分配内存&#xff09;&#xff1a; JVM可以调度使用的总的内存数&#xff0c;这个数量受操作系统进程寻址范围、系统虚拟内存总数、系统物理内存总数、其他系统运行所占用的内存资源等因素的制约。 小池塘A&a…...

SpeedTree学习笔记总结

SpeedTree是一款业界领先的三维树木植被建模软件&#xff0c;特别适用于游戏开发和影视制作。 一、基础操作 旋转&#xff1a;鼠标左键 平移&#xff1a;鼠标中键 缩放&#xff1a;鼠标中键滚动 Trunks树干节点 Branches树枝 Cap给树干封口 Frond创建大树叶 Decorations…...

【MuJoCo和PhysX】

MuJoCo 与 Unity 的 PhysX 引擎的主要区别 应用领域&#xff1a; MuJoCo&#xff1a;主要用于机器人学、强化学习、生物力学等领域&#xff0c;擅长处理多自由度、复杂动力学问题&#xff0c;尤其适合进行高精度的物理仿真。 Unity PhysX&#xff1a;主要用于游戏开发、虚拟现…...

HTML制作一个普通的背景换肤案例2024版

一&#xff0c;完整的代码&#xff1a; <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>换肤</t…...

python学opencv|读取图像(二十一)使用cv2.circle()绘制圆形进阶

【1】引言 前序已经掌握了使用cv2.circle()绘制圆形的基本操作&#xff0c;相关链接为&#xff1a; python学opencv|读取图像&#xff08;二十&#xff09;使用cv2.circle()绘制圆形-CSDN博客 由于圆形本身绘制起来比较简单&#xff0c;因此可以自由操作的空间也就大&#x…...

qt QZipReader详解

1、概述 QZipReader 是 Qt 中用于从 .zip 文件中读取和提取文件内容的类。它提供了便捷的方法来访问压缩包中的文件和目录&#xff0c;并允许你解压缩单个或多个文件。通过 QZipReader&#xff0c;你可以以编程方式读取 .zip 文件中的内容&#xff0c;并提取它们到目标目录中。…...

开发场景中Java 集合的最佳选择

在 Java 开发中&#xff0c;集合类是处理数据的核心工具。合理选择集合&#xff0c;不仅可以提高代码效率&#xff0c;还能让代码更简洁。本篇文章将重点探讨 List、Set 和 Map 的适用场景及优缺点&#xff0c;帮助你在实际开发中找到最佳解决方案。 一、List&#xff1a;有序存…...

顶顶通呼叫中心中间件mod_cti模块安全增强,预防盗打风险(mod_cti基于FreeSWITCH)

文章目录 前言联系我们mod_cti版本支持安全加强说明 前言 FreeSWITCH暴露在公网最大的风险就是被不法之人盗打 出现盗打的主要原因以下几点&#xff1a; 分机密码太简单或者密码泄露了拨号方案配置不合理sofia配置错误 所以我们给顶顶通呼叫中心中间件添加了安全加强功能&am…...

bash shell的条件语句

&#xff5e; script% touch if.sh &#xff5e; script% chmod 755 if.sh1.if-then-fi #!/usr/bin/env bashFOOD$1 if [ $FOOD"apple" ] thenecho The food is $FOOD fi exit 0~ script % ./if.sh apple The food is apple如果要将多条语句写在一行&#xff0c;可以…...

拦截器Interceptor与过滤器Filter

拦截器Interceptor 定义&#xff1a; SpringMVC内置拦截机制,允许在请求被目标方法处理的前后进行拦截&#xff0c;执行一些额外操作&#xff1b;比如&#xff1a;权限验证&#xff0c;日志记录&#xff0c;数据共享等。 实现步骤 1、自定义拦截器 Component public class …...

水电站视频智能监控系统方案设计与技术应用方案

一、背景需求 水电站作为国家重要的能源基地&#xff0c;其安全运行对于保障能源供应和社会稳定具有重要意义。然而&#xff0c;传统的人工监控方式存在着诸多问题&#xff0c;如人力成本高、监控范围有限、反应不及时等。因此&#xff0c;水电站急需引进一种先进的视频智能监控…...

教师管理系统

大概功能&#xff1a; 1.显示所有教师 2.按姓名查找教师 3.按工号查找教师 4.增加教师 5.删除教师 6.退出 数据会保存到 txt 文件里面 姓名&#xff1a;必须是中文 手机号码&#xff1a;必须是11位&#xff0c;必须是数字 效果展示&#xff1a; 代码展示&#xff1a; Teache…...

nexus docker安装

#nexus docker 安装 docker pull sonatype/nexus3 mkdir -p /data/nexus-data docker run -itd -p 8081:8081 --privilegedtrue --name nexus3 \ -v /data/nexus-data:/var/nexus-data --restartalways docker.io/sonatype/nexus3 #访问 http://192.168.31.109:8081/ 用户名&am…...

canvas之进度条

canvas之进度条 效果&#xff1a; 封装的组件 <template><div class"circle" :style"{ width: props.radius px, height: props.radius px }"><div class"circle-bg" :style"{ width: props.radius - 5 px, height: pr…...

【ES6复习笔记】Promise对象详解(12)

1. 什么是 Promise&#xff1f; Promise 是 JavaScript 中处理异步操作的一种机制&#xff0c;它可以让异步操作更加容易管理和控制。Promise 对象代表一个异步操作的最终完成或失败&#xff0c;并提供了一种方式来处理操作的结果。 2. Promise 的基本语法 Promise 对象有三…...

前端Python应用指南(五)用FastAPI快速构建高性能API

《写给前端的python应用指南》系列&#xff1a; &#xff08;一&#xff09;快速构建 Web 服务器 - Flask vs Node.js 对比&#xff08;二&#xff09;深入Flask&#xff1a;理解Flask的应用结构与模块化设计&#xff08;三&#xff09;Django vs Flask&#xff1a;哪种框架适…...

c#多线程之生产者-消费者模型

在 C# 中实现 生产者-消费者模式&#xff0c;通常需要多个线程来处理数据的生产和消费。我们可以使用 Queue<T> 来作为存储数据的队列&#xff0c;并使用 Thread、Mutex 或 Monitor 来确保线程安全。BlockingCollection<T> 是 C# 提供的一个线程安全的集合&#xf…...

2011-2020年各省城镇职工基本医疗保险年末参保人数数据

2011-2020年各省城镇职工基本医疗保险年末参保人数数据 1、时间&#xff1a;2011-2020年 2、来源&#xff1a;国家统计局 3、指标&#xff1a;省份、时间、城镇职工基本医疗保险年末参保人数 4、范围&#xff1a;31省 5、指标解释&#xff1a;参保人数指报告期末按国家有关…...

Python基础语法知识——列表、字典、元组与集合

列表&#xff08;list&#xff09;、字典(dictionary)、元组(tuple)与集合(set)都可以看成存储数据的容器&#xff0c;但是前两者常用&#xff0c;后两者用得相对较少。 目录 1 列表&#xff08;list) 1.1列表入门 1 列表&#xff08;list) 1.1列表入门 class1["李白…...

Mysql数据库中,监测某张表中某字段的修改情况(被哪个ip所修改、新老值)

在Mysql数据库中&#xff0c;通过写一个触发器&#xff0c;来监测某张表(q_device)字段(run_status)的改变情况。 【示例】 -- 1. 创建监测日志表 CREATE TABLE change_log (id INT AUTO_INCREMENT PRIMARY KEY,table_name VARCHAR(255),column_name VARCHAR(255),old_value T…...

迁移学习 详解及应用示例

简介&#xff1a; 迁移学习是一种机器学习技术&#xff0c;其核心思想是利用在一个任务上已经学到的知识&#xff08;源任务&#xff1a;任务已经有一个训练好的模型&#xff0c;然后我们将这个模型的某些部分或知识迁移到一个新的但相关的“目标任务”上。&#xff09;来帮助解…...

ubuntu控制器多网口配置

在Ubuntu系统中配置多网口&#xff0c;可以通过编辑网络配置文件&#xff08;Netplan 或旧版 /etc/network/interfaces&#xff09;实现。这适用于需要管理多个网络接口&#xff08;如 eth0、eth1 等&#xff09;的场景&#xff0c;例如负载均衡、网络隔离或多路径通信。 以下…...

接口调用限频(代理模式+滑动窗口)

目录 代码示例 接口 代理 接口实现 限流工厂 限流处理器接口 直接交换处理器 限流处理器 限流配置 滑动窗口限流 通过代理模式滑动窗口&#xff0c;限流请求第三方平台&#xff0c;避免出现第三方平台抛出限流异常&#xff0c;影响正常业务流程&#xff0c;从出口出发…...

FFmpeg在python里推流被处理过的视频流

链式算法处理视频流 视频源是本地摄像头 # codinggbk # 本地摄像头直接推流到 RTMP 服务器 import cv2 import mediapipe as mp import subprocess as sp# 初始化 Mediapipe mp_drawing mp.solutions.drawing_utils mp_drawing_styles mp.solutions.drawing_styles mp_holis…...

2- Linux系统的命令帮助

Linux 命令行帮助信息使用指南 一、引言 对于初学者来说,Linux命令行可能会显得复杂和难以捉摸。然而,一旦掌握了如何有效地利用命令行的帮助信息,您将发现它是一个强大而灵活的工具,可以极大地提高您的工作效率。本指南旨在为新手介绍如何在Linux中获取命令的帮助信息,…...

Mysql事务

一、数据库事务基础 1.1. 什么是事务 简单来说&#xff0c;事务就是要保证一组数据库操作&#xff0c;要么全部成功&#xff0c;要么全部失败。在 MySQL 中&#xff0c;事务支持是在引擎层实现的。 比如 MySQL 原生的MyISAM引擎就不支持事务&#xff0c;这也是MyISAM被InnoDB…...

Fast adaptively balanced min-cut clustering

#0.论文信息 标题&#xff1a;Fast adaptively balanced min-cut clustering期刊&#xff1a;Pattern Recognition作者: Feiping Nie , Fangyuan Xie , Jingyu Wang ,Xuelong Li机构: China Telecom, Northwestern Polytechnic al University.代码链接&#xff1a; #1.摘要 …...

vue3和springboot使用websocket通信

前端端口&#xff1a;9090 后端端口&#xff1a;8080 vue3 引入依赖&#xff1a; npm install sockjs-client stomp/stompjs vue页面 <template><div><h1>WebSocket 示例</h1><button click"sendMessage">发送消息</button>…...

Log4j2的Policies详解、SizeBasedTriggeringPolicy、TimeBasedTriggeringPolicy

文章目录 一、Policies二、SizeBasedTriggeringPolicy:基于文件大小的滚动策略2.1、文件达到指定大小就归档 三、TimeBasedTriggeringPolicy&#xff1a;基于时间间隔的滚动策略3.1、验证秒钟归档场景3.2、验证分钟场景3.3、验证小时场景 四、多策略组合使用五、扩展知识5.1、S…...

js版本之ES6特性简述【Proxy、Reflect、Iterator、Generator】(五)

目录 Proxy Reflect 静态方法 部分实例 Iterator 实际开发迭代器的使用实例 迭代器&#xff08;Iterator&#xff09;应用 Generator Proxy Proxy 是 ES6 中新增的对象 Proxy 是JavaScript中的内置对象&#xff0c;它提供了一种机制&#xff0c;可以拦截并自定义各种…...

微信V3支付报错 平台证书及平台证书序列号

1.平台证书及平台证书序列号设置错误报错&#xff1a; 错误1&#xff1a; Verify the response’s data with: timestamp1735184656, noncea5806b8cabc923299f8db1a174f3a4d0, signatureFZ5FgD/jtt4J99GKssKWKA/0buBSOAbWcu6H52l2UqqaJKvrsNxvodB569ZFz5G3fbassOQcSh5BFq6hvE…...

【开发问题记录】执行 git cz 报require() of ES Module…… 错误

文章目录 1、问题2、解决3、参考链接 1、问题 在对 commitizen 进行完&#xff0c;一系列的初始化以后 &#xff0c; 对代码进行 提交 到暂存区&#xff0c;然后要提交到 本地仓库 的报错 然后因为安装了 commitizen 所以是想用 git cz 进行提交的&#xff0c; 执行命令的时候…...

Kubernetes 安装 Nginx以及配置自动补全

部署 Nginx &#xff1a; [rootk8s-master ~]# kubectl create deployment nginx --imagenginx:1.14-alpine deployment.apps/nginx created暴露端口&#xff1a; [rootk8s-master ~]# kubectl expose deployment nginx --port80 --typeNodePort service/nginx exposed查看服…...

JS中的闭包和上下文

变量提升 和 函数提升 这里要提到一个提升的概念&#xff0c;即在JS中&#xff0c;在解析代码之前还有一个预处理的过程&#xff0c;这个过程中会把部分变量和函数声明提前到代码的最顶部&#xff0c; 会在其他所有代码之前执行。虽然当我们按照规范&#xff08;严格模式或者T…...

element-ui表格多级表头固定列和合并单元格

多级表头固定列 代码示例-不能直接运行&#xff0c;仅供参考 <el-table ref"table" class"table":data"list"style"width: 100%":header-cell-style"headerCellStyle"v-loading"dataLoading":span-method&qu…...

视频汇聚融合云平台Liveweb一站式解决视频资源管理痛点

随着5G技术的广泛应用&#xff0c;各领域都在通信技术加持下通过海量终端设备收集了大量视频、图像等物联网数据&#xff0c;并通过人工智能、大数据、视频监控等技术方式来让我们的世界更安全、更高效。然而&#xff0c;随着数字化建设和生产经营管理活动的长期开展&#xff0…...

第五十九章 假脱机设备

文章目录 第五十九章 假脱机设备介绍打开和使用假脱机设备用于假脱机设备的 OPEN 和 USE 命令USE 命令 第五十九章 假脱机设备 介绍 IRIS数据平台使能够将打印输出直接发送到您的打印机或屏幕&#xff0c;或将其保留在后台打印中以供以后打印。IRIS 假脱机独立于您的操作系统…...

Maven Wrapper 报错“未找到有效的 Maven 安装”

1. 检查 Maven Wrapper 配置&#xff1a; 确保你的项目中包含 .mvn/wrapper/maven-wrapper.properties 文件。 检查该文件中的 distributionUrl 属性&#xff0c;确保它指向一个有效的 Maven 发行版 URL。 2.确认 Maven Wrapper 脚本存在&#xff1a; 在项目根目录下&#x…...

yarn list --pattern vuex-module-decorators

dgqdgqdeMac-mini spid-admin % yarn list --pattern vuex-module-decorators yarn list v1.22.22 └─ vuex-module-decorators0.16.1 ✨ Done in 0.24s.好的&#xff0c;这段代码是一个典型的 Vuex 模块定义&#xff0c;使用了 vuex-module-decorators 库。这个库为 Vuex 提…...

day19-Linux软件包

科普&#xff0c;什么是代码文件。 电脑程序Program&#xff0c;就是某一个编程语言编写的一个代码文件&#xff0c;里面包含了该语言特有的指令&#xff0c;以及各种字符、符号。 linux自带的network管理脚本&#xff0c;shell脚本 什么是软件程序。 软件程序&#xff0c;就…...

【网络分析工具】WireShark的使用(超详细)

网络分析工具——WireShark的使用 简介WireShark软件安装Wireshark 开始抓包示例WireShark抓包界面WireShark 主要分为这几个界面TCP包的具体内容Wireshark过滤器设置wireshark过滤器表达式的规则Wireshark抓包分析TCP三次握手Wireshark分析常用操作 简介 WireShark是非常流…...

React 高级组件开发:动态逻辑与性能优化

React 高级组件开发&#xff1a;动态逻辑与性能优化 引言一、动态逻辑与配置化组件1. 动态组件的设计 二、自定义 Hooks 解决复杂状态管理1. 自定义 Hook 的优势 三、高阶组件&#xff08;HOC&#xff09;模式1. 高阶组件的应用场景 四、性能优化1. 使用 React.memo 优化渲染2.…...

Vue 3 与 Tauri 集成开发跨端APP

1、安装RUST 下载地址&#xff1a;Install Rust - Rust Programming Language 安装&#xff1a; 安装完成后&#xff0c;在命令行里运行: rustup 2、安装 Node.js 与 npm 或 pnpm &#xff0c;如果已经安装&#xff0c;可以忽略 # 使用 nvm 安装 Node.js 最新版本 nvm install…...

FreeRTOS中xPortPendSVHandler()和vPortSVCHandler()这两个函数的作用

在 FreeRTOS 中&#xff0c;xPortPendSVHandler() 和 vPortSVCHandler() 是两个重要的中断服务例程&#xff08;ISR&#xff09;&#xff0c;它们负责处理与操作系统相关的异常。这些函数对于实现上下文切换和任务管理至关重要。下面分别解释这两个函数的作用&#xff1a; xPo…...