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

Python+Appium微信自动化实战:从环境搭建到消息自动发送

1. 项目概述:为什么选择Python+Appium来操作微信?

如果你是一名测试工程师、爬虫开发者,或者只是想把自己从一些重复的微信操作中解放出来的效率追求者,那么“用代码控制微信”这个想法一定在你脑海里出现过不止一次。市面上有很多所谓的“微信机器人”框架,但它们要么依赖有封号风险的网页协议,要么就是封装得黑盒一般,出了问题无从排查。而Python + Appium这套组合,走的是一条截然不同的“阳光大道”——它模拟的是真实用户的手指操作。

简单来说,Appium是一个移动端自动化测试框架,它通过标准协议(WebDriver)来驱动手机上的原生App。Python则是我们向Appium发送指令的“指挥官”。这套方案的底层逻辑是:你的代码通过Appium Server告诉手机系统:“请在屏幕坐标(X, Y)点一下”,或者“请找到这个ID为‘com.tencent.mm:id/abc’的按钮并点击”。手机系统照做,整个过程和你自己用手指操作一模一样。正因如此,它的稳定性极高,几乎不会触发微信的安全机制,因为从系统的视角看,这就是一个正常的用户在操作。

我选择这条路,最初是为了做App的UI自动化测试。后来发现,用它来处理一些个人微信的琐事,比如自动通过好友请求并打标签、定时给特定群发消息、或者备份一些聊天记录到本地,简直是大材小用般的顺手。它不破解协议、不注入内存,是所有方案里最“老实”也最安全的一种。当然,它的缺点也很明显:速度比不上协议接口,并且必须有一台真实的手机或模拟器在运行。但对于需要高稳定性、且对实时性要求不是极端高的场景,它是目前综合来看最好的选择。

2. 环境搭建:从零开始的踩坑指南

万事开头难,环境配置是劝退很多人的第一道坎。这里我会把每一步的原理和可能遇到的坑都讲清楚,确保你能一次成功。

2.1 核心三件套:Python、Appium Server、客户端库

Python环境:这是我们的脚本运行环境。建议直接安装Python 3.8或3.9版本,这两个版本与各类库的兼容性最好。不要使用太新的版本,以免遇到依赖库尚未适配的问题。安装时务必勾选“Add Python to PATH”,这是为了能在命令行任何位置直接调用pythonpip命令。

安装完成后,打开命令行(CMD或PowerShell),输入python --versionpip --version验证。如果提示“不是内部或外部命令”,说明环境变量没配置好,需要手动将Python的安装目录(如C:\Python39)和脚本目录(如C:\Python39\Scripts)添加到系统的PATH变量中。

Appium Server:这是连接手机和Python脚本的“桥梁”或“翻译官”。有两种安装方式:

  1. 桌面版(Appium Desktop):对于新手极度友好。它提供了一个图形界面,里面集成了用于元素定位的Inspector工具。你可以从官网下载安装包,一键安装。启动后,一个简单的Host和Port设置界面就出来了,点击启动按钮,后台服务就跑起来了。
  2. 命令行版(Appium Server via NPM):更轻量,更适合集成到CI/CD流水线。这需要你先安装Node.js,然后通过npm命令安装:npm install -g appium。安装后,在命令行输入appium即可启动服务。

注意:初次运行Appium Desktop或命令行版,可能会自动安装一些必要的驱动程序(如uiautomator2xcuitest)。请保持网络通畅。如果遇到权限问题,在Windows上请以管理员身份运行命令行或Appium Desktop。

Python客户端库:这就是我们的“指挥棒”。在命令行里运行:pip install Appium-Python-Client。这个库封装了向Appium Server发送指令的所有细节,让我们能用简单的Python代码完成复杂的操作。

2.2 手机端准备:开发者选项与调试

要让电脑控制手机,必须在手机上开启“开发者模式”和“USB调试”。不同品牌手机开启方式略有差异,通常是在“设置”-“关于手机”里,连续点击“版本号”7次,会提示你已进入开发者模式。

然后,在“设置”-“系统和更新”(或“更多设置”)里找到“开发者选项”,打开“USB调试”和“USB调试(安全设置)”(如果有的话)。如果是小米等品牌,可能还需要额外打开“USB安装”和“USB调试(安全设置)”。

用数据线连接手机和电脑。连接后,手机会弹出“是否允许USB调试”的对话框,勾选“始终允许”,并点击确定。这是关键一步,否则电脑无法识别设备。

在电脑命令行输入adb devices,如果看到你的设备号后面显示device(而不是unauthorized),说明连接成功。ADB(Android Debug Bridge)是Android SDK里的一个工具,Appium底层依赖它来与设备通信。如果提示找不到adb命令,你需要单独下载Android SDK Platform-Tools,并将其路径添加到系统PATH中。

2.3 第一个连接脚本:验证环境

环境搭好了,我们来写一个最简单的脚本验证一切是否正常。这个脚本的目标是:启动Appium Server,连接手机,然后打开微信。

from appium import webdriver from appium.options.android import UiAutomator2Options import time # 1. 定义设备能力和App信息 desired_caps = { 'platformName': 'Android', # 平台,固定为Android或iOS 'platformVersion': '12', # 你的手机安卓版本,在设置里查看 'deviceName': '你的设备名', # 自定义,用于在日志中标识,可随意写 'appPackage': 'com.tencent.mm', # 微信的包名 'appActivity': '.ui.LauncherUI', # 微信的启动Activity 'noReset': True, # 是否在会话前重置App状态。True表示不重置,保留登录态。 'automationName': 'UiAutomator2', # 自动化引擎,Android上推荐用这个 'newCommandTimeout': 600 # 新命令超时时间,单位秒,防止长时间无操作断开 } # 2. 将配置转换为Appium-Python-Client接受的Options对象(推荐新写法) options = UiAutomator2Options().load_capabilities(desired_caps) # 3. 连接Appium Server # 确保Appium Server已经在默认的 http://127.0.0.1:4723 运行 driver = webdriver.Remote('http://127.0.0.1:4723', options=options) # 4. 等待几秒,看看微信是否成功打开 time.sleep(5) # 5. 打印当前页面结构(可选,用于调试) print(driver.page_source) # 6. 关闭会话 driver.quit()

把上面代码中的platformVersiondeviceName替换成你自己的信息,然后运行。如果一切顺利,你会看到手机自动解锁并打开了微信。如果卡住了或者报错,别慌,我们接着往下看。

3. 核心操作解析:定位元素与模拟交互

自动化操作的核心就两步:找到元素操作元素。在移动端,元素就是屏幕上的按钮、输入框、文本区域等。

3.1 元素定位的“北斗七星”:七大策略

Appium提供了多种定位元素的方式,就像不同的地图导航工具。没有绝对最好的,只有最适合当前场景的。

  1. ID定位 (resource-id):最优先选择。相当于元素的身份证号,通常是唯一的。在微信里,很多关键按钮都有ID,比如通讯录按钮的ID可能是com.tencent.mm:id/brx。用法:driver.find_element(AppiumBy.ID, “com.tencent.mm:id/brx”)
  2. Accessibility ID定位 (content-desc):次优选择。这是为无障碍功能设计的描述,对于重要的图标按钮,开发同学有时会设置。如果ID不稳定,可以看这个。
  3. XPath定位:最强大也最复杂。它通过元素的路径结构来定位,当元素没有ID和描述时,这是终极武器。例如://android.widget.TextView[@text=“发现”]。但XPath性能相对较差,且容易因UI改动而失效。
  4. Class Name定位:按元素类型定位,如android.widget.Button。通常一个页面有很多同类型元素,所以很少单独使用,常与其他条件结合。
  5. Android UIAutomator定位 (仅Android):使用Android自带的UIAutomator API进行定位,功能强大,支持滚动查找等。例如:driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, ‘new UiSelector().text(“通讯录”)’)
  6. iOS Predicate String / Class Chain (仅iOS):在iOS平台上的高级定位方式。
  7. 坐标定位:万不得已的下下策。直接指定屏幕坐标(x, y)进行点击。driver.tap([(x, y)])。缺点显而易见:不同分辨率手机坐标完全不同,兼容性极差。

实操心得:在微信自动化中,优先尝试用ID和Accessibility ID。对于列表中的项目(如聊天列表、通讯录列表),通常需要结合XPath或UIAutomator进行文本匹配。一个黄金法则是:多用相对定位,少用绝对索引。不要用find_elements(...)[3]这种方式,因为列表顺序可能变化。用文本内容或部分特征来定位更稳定。

3.2 使用Appium Inspector进行“侦查”

你怎么知道一个元素的ID或XPath是什么?这就需要用到“侦查工具”——Appium Inspector。它是Appium Desktop的一部分。

使用步骤:

  1. 启动Appium Desktop,点击“Start Server”。
  2. 点击“Start Inspector Session”按钮。
  3. 在弹出的窗口中,填入之前脚本里的desired_caps配置信息。
  4. 点击“Start Session”,你的手机屏幕镜像就会显示在电脑上。
  5. 点击屏幕上的元素,右侧就会显示该元素的所有属性,包括resource-id,text,content-desc,class,以及系统帮你生成的XPath。

Inspector是你探索App界面结构的眼睛,写脚本前,一定要用它把目标操作路径上的关键元素属性记录下来。

3.3 基础交互API:点击、输入、滑动

找到元素后,就可以操作了。以下是最常用的几个方法:

  • 点击element.click()
  • 输入文本element.send_keys(“你好,世界!”)。注意,输入前最好先element.clear()一下清空原有内容。
  • 获取文本text = element.text
  • 滑动:这是一个稍微复杂点的操作,因为需要指定起始点和结束点坐标。Appium提供了driver.swipe(start_x, start_y, end_x, end_y, duration)方法,其中duration是滑动耗时(毫秒),时间越长滑动越慢。更推荐使用driver.scroll(origin_el, destination_el)driver.drag_and_drop(origin_el, destination_el)进行元素到元素的滑动。
  • 等待:这是自动化脚本稳定的关键。不要用固定的time.sleep(),而要用显式等待
    from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from appium.webdriver.common.appiumby import AppiumBy # 等待最多10秒,直到“发现”这个文本出现 element = WebDriverWait(driver, 10).until( EC.presence_of_element_located((AppiumBy.ANDROID_UIAUTOMATOR, ‘new UiSelector().text(“发现”)’)) ) element.click()
    显式等待只在条件满足时立即执行,否则超时抛异常,这比傻等固定时间高效和可靠得多。

4. 实战案例:编写一个自动发送消息的脚本

现在,我们综合运用以上知识,完成一个实际案例:自动打开与某个联系人的聊天窗口,并发送一条指定消息。

目标:找到微信通讯录里的“文件传输助手”,发送“这是一条自动化测试消息”。

步骤拆解

  1. 启动微信,确保在主界面。
  2. 点击底部导航栏的“通讯录”按钮。
  3. 在通讯录顶部搜索框,输入“文件传输助手”。
  4. 在搜索结果中,点击“文件传输助手”。
  5. 进入聊天界面后,点击输入框。
  6. 输入消息内容。
  7. 点击发送按钮。

代码实现与详解

from appium import webdriver from appium.options.android import UiAutomator2Options from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from appium.webdriver.common.appiumby import AppiumBy import time # 初始化驱动 desired_caps = { ‘platformName’: ‘Android’, ‘platformVersion’: ‘12’, ‘deviceName’: ‘MyPhone’, ‘appPackage’: ‘com.tencent.mm’, ‘appActivity’: ‘.ui.LauncherUI’, ‘noReset’: True, ‘automationName’: ‘UiAutomator2’, ‘unicodeKeyboard’: True, # 使用Unicode编码方式发送字符串,支持中文 ‘resetKeyboard’: True, # 重置键盘,防止输入法冲突 } options = UiAutomator2Options().load_capabilities(desired_caps) driver = webdriver.Remote(‘http://127.0.0.1:4723’, options=options) wait = WebDriverWait(driver, 15) # 设置一个全局的显式等待对象,超时15秒 try: # 步骤1:等待主界面加载完成,通常可以通过等待“微信”标题或底部导航栏出现来判断 print(“等待微信主界面…”) # 这里用一个底部Tab的ID来作为主界面加载完成的标志 wait.until(EC.presence_of_element_located((AppiumBy.ID, “com.tencent.mm:id/bpx”))) # 假设这是“微信”Tab的ID # 步骤2:点击“通讯录”Tab print(“点击通讯录…”) # 通过Inspector找到“通讯录”Tab的ID或描述。这里用文本定位示例。 contacts_tab = wait.until(EC.element_to_be_clickable((AppiumBy.ANDROID_UIAUTOMATOR, ‘new UiSelector().text(“通讯录”)’))) contacts_tab.click() # 步骤3:点击通讯录顶部的搜索框 print(“点击搜索框…”) # 搜索框通常是一个可点击的View,有固定的ID search_box = wait.until(EC.element_to_be_clickable((AppiumBy.ID, “com.tencent.mm:id/ht”))) # 这个ID需要你用Inspector确认 search_box.click() # 步骤4:在搜索输入框中输入“文件传输助手” print(“输入搜索关键词…”) # 点击搜索框后,会弹出一个新的输入框,需要重新定位 input_box = wait.until(EC.presence_of_element_located((AppiumBy.ID, “com.tencent.mm:id/ht”))) # 可能和搜索框是同一个ID,也可能是新的 input_box.clear() input_box.send_keys(“文件传输助手”) time.sleep(2) # 等待搜索结果刷新,这里可以用更智能的等待,比如等待结果列表出现 # 步骤5:在搜索结果中点击“文件传输助手” print(“选择联系人…”) # 搜索结果通常是一个列表,每一项包含头像和名称。我们通过文本精准定位。 # 注意:这里用‘textContains’比‘text’更稳妥,防止有额外空格或后缀 contact_item = wait.until(EC.element_to_be_clickable((AppiumBy.ANDROID_UIAUTOMATOR, ‘new UiSelector().textContains(“文件传输助手”)’))) contact_item.click() # 步骤6:等待进入聊天页面,并定位输入框 print(“进入聊天界面,定位输入框…”) chat_input = wait.until(EC.presence_of_element_located((AppiumBy.ID, “com.tencent.mm:id/al_”))) # 输入框ID,需用Inspector确认 chat_input.click() chat_input.send_keys(“这是一条由Python+Appium发送的自动化测试消息。”) # 步骤7:点击发送按钮 print(“点击发送…”) send_btn = wait.until(EC.element_to_be_clickable((AppiumBy.ID, “com.tencent.mm:id/aln”))) # 发送按钮ID,需用Inspector确认 send_btn.click() print(“消息发送成功!”) time.sleep(3) # 看一眼发送结果 except Exception as e: print(f“操作过程中出现错误:{e}”) # 可以在这里截屏保存现场,便于排查 driver.save_screenshot(‘error_screenshot.png’) finally: # 步骤8:关闭会话 driver.quit()

关键点与避坑指南

  1. ID是动态的:最重要的一点!微信不同版本、甚至不同账号状态下,元素的resource-id可能会变!上面代码中的ID(如com.tencent.mm:id/ht只是示例,你必须使用Appium Inspector连接你的手机和微信版本,亲自查看并记录下正确的ID。这是写微信自动化脚本最核心的一步。
  2. 等待的艺术:脚本里混合使用了WebDriverWait显式等待和少量的time.sleep。对于网络请求后的UI刷新(如搜索),time.sleep有时更简单粗暴且有效。但在可能的情况下,优先使用显式等待,条件可以是元素出现、可点击、可见等。
  3. 输入法问题:配置中unicodeKeyboardresetKeyboard是为了解决中文输入和输入法弹窗遮挡的问题。如果遇到输入框点击后弹不出键盘,或输入的是乱码,可以检查这两项配置。
  4. 页面切换:从主界面到通讯录,再到聊天窗口,这是页面Activity的切换。Appium有时需要一点时间来适应新的Activity。在关键步骤后增加短暂等待或使用等待新页面特征元素出现,能提高稳定性。

5. 进阶技巧与稳定性优化

一个能跑起来的脚本和一個能在不同环境下稳定运行的脚本,中间隔着无数个坑。下面分享一些提升脚本鲁棒性的经验。

5.1 封装与Page Object模式

当脚本越来越长,直接在主流程里写大量的find_elementclick会让代码难以维护。业界最佳实践是采用Page Object (PO) 模式。其核心思想是将每个页面(如微信主界面、通讯录页、聊天页)封装成一个类,这个类包含该页面的元素定位符和基本操作方​​法。

例如,创建一个ChatPage类:

class ChatPage: def __init__(self, driver): self.driver = driver self.wait = WebDriverWait(driver, 10) @property def input_box(self): return self.wait.until(EC.presence_of_element_located((AppiumBy.ID, “com.tencent.mm:id/al_”))) @property def send_button(self): return self.wait.until(EC.element_to_be_clickable((AppiumBy.ID, “com.tencent.mm:id/aln”))) def send_message(self, text): self.input_box.click() self.input_box.send_keys(text) self.send_button.click()

这样,在主脚本里,代码就会变得非常清晰:

from pages.chat_page import ChatPage # … 初始化driver … chat_page = ChatPage(driver) chat_page.send_message(“Hello from PO模式!”)

5.2 异常处理与重试机制

网络波动、手机卡顿、元素加载慢都会导致脚本失败。完善的异常处理和重试机制是必须的。

  • Try-Except块:像上面的实战代码一样,用try...except...finally包裹核心流程,确保出错时能记录日志、保存截图,并安全关闭驱动。
  • 重试装饰器:对于不可靠的操作(如点击某个偶尔加载慢的按钮),可以写一个重试装饰器。
    import functools import time def retry(times=3, delay=1): def decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): for i in range(times): try: return func(*args, **kwargs) except Exception as e: if i == times - 1: raise e print(f”{func.__name__} 第{i+1}次尝试失败,{delay}秒后重试…“) time.sleep(delay) return wrapper return decorator # 使用 @retry(times=3, delay=2) def click_unstable_button(driver): driver.find_element(AppiumBy.ID, “some_unstable_id”).click()

5.3 处理弹窗与权限

自动化过程中,最讨厌的就是突如其来的系统弹窗或App内的广告弹窗。它们会遮挡目标元素,导致定位失败。

  • 预期弹窗:比如首次启动的权限申请。可以在desired_caps中预先授权:‘autoGrantPermissions’: True。但这不是万能的。
  • 非预期弹窗:需要一个弹窗监控与处理机制。思路是:在执行任何操作前,先检查屏幕上是否出现了已知的弹窗元素(如“允许”、“拒绝”、“确定”按钮),如果出现了,就点击处理掉。
    def handle_popups(driver): popup_selectors = [ (AppiumBy.ID, “android:id/button1”), # 系统确定按钮 (AppiumBy.ID, “com.android.packageinstaller:id/permission_allow_button”), # 权限允许 (AppiumBy.XPATH, “//*[contains(@text, ‘确定’)]”), # 文本包含确定的按钮 # 添加你遇到的微信特定弹窗定位符 ] for by, selector in popup_selectors: try: # 快速查找,不等待 element = driver.find_element(by, selector) element.click() print(f”检测并点击了弹窗:{selector}“) time.sleep(0.5) # 点击后稍作等待 except: pass
    在关键操作步骤前调用这个函数。

5.4 多设备管理与并行

如果你需要管理多台手机,或者进行并行测试,手动修改desired_caps里的deviceNameudid(设备唯一标识)很麻烦。可以通过读取设备列表来自动化。

  1. 使用adb devices命令获取所有已连接设备的UDID。
  2. 为每个设备启动一个独立的Appium Server进程(需要指定不同的端口,如4723, 4725, 4727…)。
  3. 为每个设备创建独立的driver对象,并分配不同的udid和Appium Server地址。

这通常需要结合多线程或concurrent.futures库来实现。对于个人简单任务,管理一台设备就足够了。

6. 常见问题排查与解决方案实录

在实际操作中,你会遇到各种各样的问题。这里记录了一些典型问题和我的解决思路。

问题现象可能原因排查步骤与解决方案
WebDriverException: Message: An unknown server-side error occurred1. Appium Server未启动或端口被占用。
2.desired_caps配置错误(如appActivity不对)。
3. 手机未连接或未授权USB调试。
1. 检查Appium Server日志(命令行或Desktop的日志窗口),看是否有明显错误。
2. 运行adb devices确认设备状态为device
3. 核对appPackageappActivity。可以用adb shell dumpsys window | grep mCurrentFocus查看当前前台Activity。
NoSuchElementException找不到元素1. 元素定位符写错了(最常见)。
2. 页面尚未加载完成,元素还不存在。
3. 元素在WebViewFlutter等混合渲染引擎内,需要切换上下文(Context)。
4. 页面有弹窗遮挡。
1. 用Appium Inspector重新侦查,确认定位符。
2. 增加显式等待时间,或改用更稳定的等待条件(如element_to_be_clickable)。
3. 打印driver.contexts查看所有上下文,并使用driver.switch_to.context(‘WEBVIEW_xxx’)切换到正确的WebView上下文。微信小程序、公众号文章页等需要此操作。
4. 运行弹窗处理函数。
脚本在输入框无法输入中文1. 未启用unicodeKeyboardresetKeyboard
2. 手机输入法冲突。
1. 在desired_caps中确保这两项为True
2. 在手机系统设置中,将默认输入法切换为系统自带的“Android键盘(AOSP)”或类似选项,避免第三方输入法。
点击操作无效,但也不报错1. 点击的坐标点恰好是元素不可点击的区域(如图标边缘)。
2. 元素被另一个透明层覆盖。
3. 需要的是“长按”而不是“点击”。
1. 尝试用driver.tap([(x, y)])点击元素中心点坐标。用element.locationelement.size计算中心点。
2. 尝试使用driver.execute_script(‘mobile: clickGesture’, {‘x’: x, ‘y’: y})这种底层手势。
3. 使用TouchAction(driver).long_press(element).release().perform()进行长按。
脚本运行速度慢1. 大量使用time.sleep()
2. 隐式等待driver.implicitly_wait()设置时间过长。
3. 元素定位策略效率低(如复杂XPath)。
1. 用显式等待WebDriverWait替代固定休眠。
2. 将隐式等待时间设短(如5秒),或干脆不用,全靠显式等待。
3. 优化定位符,优先用ID,其次Accessibility ID,最后才用XPath。避免使用//*这种全路径搜索。
Appium Inspector无法连接或截屏是黑的1. 手机屏幕锁屏了。
2. 电脑和手机不在同一网络(对于无线调试)。
3. 手机系统版本过高,需要特殊设置(如小米的“USB调试(安全设置)”)。
1. 确保手机屏幕是亮的且未锁屏。
2. 如果使用无线调试,确保adb connect <手机IP>成功。
3. 检查手机开发者选项中的所有USB调试相关选项是否都已打开。对于Android 11+,可能还需要开启“无线调试”下的“使用配对码配对设备”。

最后,也是最关键的一点:微信的UI结构并非为自动化设计,它的ID和布局可能随版本更新而改变。因此,你的脚本需要定期使用最新版的Appium Inspector进行复查和更新定位符。将定位符集中管理在配置文件或Page Object类中,可以最大程度降低维护成本。自动化不是一劳永逸的,而是一个需要持续维护和适配的过程。但一旦跑通,它为你节省的时间和带来的便利,绝对是值得的。

http://www.jsqmd.com/news/1082537/

相关文章:

  • ExtractorSharp:5分钟解锁游戏资源编辑的终极指南
  • HM-RAG 分层多智能体架构:破解多模态检索增强生成的落地难题
  • 毕设分享 yolov11焊接缺陷检测识别系统(源码+论文)
  • Hotkey Detective:Windows热键冲突的终极侦探,3分钟找回你的快捷键控制权
  • 如何用100+插件让RPG Maker MV/MZ游戏焕然一新
  • 思源宋体完整实战指南:7种字重免费打造专业中文排版
  • 续航、安全、舒适的“热”钥匙:数字化赋能新能源汽车热管理升级
  • 从零搭建私有云服务:基于Docker与VPS的自建网络实践指南
  • 3大实战技巧:快速掌握开源德州扑克GTO策略分析工具
  • Windows热键被“偷“了怎么办?这个开源工具帮你快速揪出“元凶“
  • Arachni开源Web漏洞扫描器:从原理到实战的自动化安全测试指南
  • NMS算法
  • Agent开发——Day 04 async/await 异步编程
  • 「简记往来」开发历程系列:API设计——RESTful接口在礼账场景中的实践
  • 4G+LoRa远程土壤监测系统设计与实现
  • 2026年自动化运维产品深度对比:破解异构架构与合规高效双重挑战
  • 创建vue3项目(使用vite) + 配置路由router
  • Windows热键侦探:快速定位热键冲突的完整解决方案
  • 2025年最强网盘直链下载工具:LinkSwift全面使用手册
  • 告别文献管理噩梦:WPS-Zotero插件如何让你的科研写作效率提升10倍
  • 计算机Java毕设实战-基于 SpringBoot 的智慧旅游推荐平台的设计与实现 基于 SpringBoot 的旅游信息推荐系统的设计与实现【完整源码+LW+部署说明+演示视频,全bao一条龙等】
  • 计算机毕业设计之基于微信小程序的校园订餐配送系统的设计与实现
  • 【Ultra-Fusion】一套后端通吃轮式/四足/无人机:因子级退化调度+在线时空校准,60+系统对比全SOTA
  • 如何快速掌握STDF-Viewer:半导体测试数据可视化的终极指南
  • 树莓派5搭载Hailo NPU部署本地大语言模型实战指南
  • MetaboAnalystR 代谢组学分析终极指南:从入门到精通
  • 从零搭建Fastjson 1.2.24反序列化漏洞靶场:原理、实战与深度避坑
  • 4G MQTT物联网气象监测终端设计与优化
  • GARbro终极指南:5个简单步骤掌握视觉小说资源提取神器
  • 系统高可用架构实战:从原理到实践构建安全岛保障业务连续性