跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Python大前端

Selenium 常用操作 API 指南

Selenium 自动化测试涵盖元素属性获取、窗口控制、滚动条处理、截图、多窗口切换、Frame 切换、等待机制、鼠标键盘操作、弹框及下拉框处理。通过显式等待解决加载问题,利用 JavaScript 执行高级操作。针对验证码提供万能码、Cookie 绕过、第三方打码及本地 OCR 四种方案。最后总结常见定位失败排查清单及最佳实践速查表,提升脚本稳定性。

活在当下发布于 2026/3/23更新于 2026/9/1164 浏览

1. 元素本身属性操作

获取元素状态或内容,用于断言或逻辑判断。

# 假设已定位到元素:element = driver.find_element(By.ID, "xxx")

# 1. 获取元素文本 (获取标签对之间的文本,不含 HTML 标签)
text_content = element.text

# 2. 判断元素是否被选中 (常用于单选框 radio、复选框 checkbox)
is_checked = element.is_selected() # 返回 True/False

# 3. 判断元素是否可用 (未被 disabled 禁用)
is_usable = element.is_enabled() # 返回 True/False

# 4. 判断元素是否可见 (在页面上显示且宽高不为 0)
is_visible = element.is_displayed() # 返回 True/False

# 模拟点击:element.click()
# 模拟输入:element.send_keys()
# 模拟清除:element.clear()
# 页面刷新:driver.refresh()

2. 浏览器窗口操作

控制浏览器窗口的行为和生命周期。

# 1. 最大化窗口
driver.maximize_window()

# 2. 刷新页面
driver.refresh()

# 3. 后退 (相当于点击浏览器后退按钮)
driver.back()

# 4. 前进 (相当于点击浏览器前进按钮)
driver.forward()

# 5. 退出 (关闭所有关联窗口并结束驱动进程,务必在脚本末尾使用)
driver.quit()
# 注意:driver.close() 仅关闭当前焦点窗口

3. 滚动条处理 (JavaScript 执行)

Selenium 无法直接操作滚动条,需通过执行 JS 代码实现。

# 1. 定义 JS 字符串
# 方式 A: 滚动到绝对坐标 (x=横向,y=纵向)
js_scroll_abs = "window.scrollTo(0, 500)"

# 方式 B: 滚动到底部
js_scroll_bottom = "window.scrollTo(0, document.body.scrollHeight)"

# 方式 C: 滚动到特定元素位置 (需先定位元素)
# element = driver.find_element(By.ID, "footer")
# js_scroll_elem = "arguments[0].scrollIntoView();"

# 2. 执行 JS 代码
driver.execute_script(js_scroll_abs)

4. 截图处理

用于自动化测试失败时的现场保留或验证。

# 截取整个页面并保存为文件 (参数为文件路径,支持 .png)
driver.get_screenshot_as_file("./screenshots/error_page.png")

# 或者获取二进制数据 (不保存文件,用于内存处理)
# img_data = driver.get_screenshot_as_png()

5. 多窗口/标签页切换

当点击链接打开新标签页时,需切换句柄(Handle)才能操作新窗口。

# 1. 获取所有窗口句柄 (列表形式)
handles = driver.window_handles

# 2. 切换到指定窗口 (通过下标或具体句柄值)
# 切换到最新打开的窗口 (通常是列表最后一个)
driver.switch_to.window(handles[-1])

# 切换到第一个窗口
driver.switch_to.window(handles[0])

# 3. (可选) 关闭当前窗口后切回主窗口
# driver.close()
# driver.switch_to.window(driver.window_handles[0])

6. Frame/Iframe 切换

若元素位于 <iframe> 或 <frame> 内部,必须先切换进入,操作完后再切出。

# 1. 定位到 frame 元素
frame_element = driver.find_element(By.ID, "login_frame")
# 或者直接通过 ID/Name 字符串:driver.switch_to.frame("login_frame")

# 2. 切换到该 frame (之后只能操作 frame 内部的元素)
driver.switch_to.frame(frame_element)
# ... 执行内部元素操作 ...

# 3. 切回主文档 (默认内容),以便操作外部元素
driver.switch_to.default_content()

# (可选) 切换到父级 frame (若嵌套多层)
# driver.switch_to.parent_frame()

7. 时间等待机制

解决页面加载慢导致的 NoSuchElementException。

A. 强制等待 (不推荐作为主要手段)
import time
# 程序暂停执行指定秒数,无论页面是否加载完成
time.sleep(5)
B. 隐式等待 (全局设置)
# 设置全局超时时间。若元素未立即出现,轮询查找直到超时。
# 只需设置一次,对后续所有 find_element 生效。
driver.implicitly_wait(10)
C. 显式等待 (推荐,局部精准控制)

配合 WebDriverWait 和 expected_conditions (EC) 使用。

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

# 初始化等待对象:最大等待 10 秒,每 0.5 秒检查一次
wait = WebDriverWait(driver, 10, poll_frequency=0.5)

# 场景 1: 等待元素可见 (推荐,确保元素不仅能找到,还能交互)
element = wait.until(
    EC.visibility_of_element_located((By.ID, "username"))
)

# 场景 2: 等待元素存在 (仅在 DOM 中,不一定可见)
element = wait.until(
    EC.presence_of_element_located((By.ID, "username"))
)

# 场景 3: 等待元素可点击
element = wait.until(
    EC.element_to_be_clickable((By.ID, "submit_btn"))
)

# 场景 4: 自定义条件 (Lambda 表达式)
element = wait.until(
    lambda x: x.find_element(By.ID, "dynamic_content")
)

8. 鼠标与键盘操作

用于处理悬停 (Hover)、拖拽 (Drag & Drop)、右键点击、双击等复杂交互。

from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys

# 1. 初始化动作链
actions = ActionChains(driver)

# 2. 鼠标悬停 (二级菜单常用)
# 先定位到父级菜单元素
menu_element = driver.find_element(By.ID, "menu_item")
actions.move_to_element(menu_element).perform()
# .perform() 必须调用以执行动作

# 3. 右键点击
# actions.context_click(element).perform()

# 4. 双击
# actions.double_click(element).perform()

# 5. 拖拽 (从源元素拖到目标元素)
# source = driver.find_element(By.ID, "drag")
# target = driver.find_element(By.ID, "drop")
# actions.drag_and_drop(source, target).perform()

# 6. 键盘组合键 (如:Ctrl+A 全选,Ctrl+C 复制)
# input_box = driver.find_element(By.ID, "content")
# input_box.send_keys(Keys.CONTROL, "a") # 全选
# input_box.send_keys(Keys.CONTROL, "c") # 复制

9. 浏览器原生弹框处理

针对 window.alert, window.confirm, window.prompt 生成的原生弹窗,无法用普通元素定位。

from selenium.webdriver.common.alert import Alert

# 1. 切换到弹框
alert = driver.switch_to.alert

# 2. 获取弹框文本内容
alert_text = alert.text

# 3. 点击'确定' (接受)
alert.accept()

# 4. 点击'取消' (解散,仅适用于 confirm/prompt)
# alert.dismiss()

# 5. 在 prompt 弹框中输入内容
# alert.send_keys("输入的内容")
# alert.accept()

10. 下拉框处理 (Select)

针对标准的 <select> 标签,Selenium 提供了专用类 Select。

from selenium.webdriver.support.ui import Select

# 1. 定位到 select 元素
select_element = driver.find_element(By.ID, "province")
dropdown = Select(select_element)

# 2. 通过可见文本选择
dropdown.select_by_visible_text("北京市")

# 3. 通过 value 属性值选择
dropdown.select_by_value("BJ")

# 4. 通过索引选择 (从 0 开始)
dropdown.select_by_index(1)

# 5. 取消选择 (仅支持多选下拉框)
# dropdown.deselect_all()
# dropdown.deselect_by_visible_text("北京市")

# 6. 判断是否多选
is_multi = dropdown.is_multiple

11. 其他 JavaScript 高级用法

除了滚动条,JS 还可用于修改元素属性(绕过前端限制)或直接点击。

# 1. 移除元素的 disabled 属性 (强制启用按钮)
# btn = driver.find_element(By.ID, "submit_btn")
# driver.execute_script("arguments[0].removeAttribute('disabled')", btn)

# 2. 直接通过 JS 点击元素 (当 element.click() 被遮挡或失效时)
# driver.execute_script("arguments[0].click()", btn)

# 3. 修改输入框的值 (绕过某些监听事件限制)
# input_box = driver.find_element(By.ID, "username")
# driver.execute_script("arguments[0].value='admin'", input_box)

# 4. 获取页面标题或当前 URL (通常直接用 driver.title / driver.current_url,但也可用 JS)
# title = driver.execute_script("return document.title")

12. 定位不到元素?排查清单 (Troubleshooting)

当报错 NoSuchElementException 或 ElementNotInteractableException 时,按此顺序检查:

序号可能原因解决方案
1元素未加载页面慢,元素还没出来。解决:加显式等待 (WebDriverWait)。
2在 Frame 里元素在 <iframe> 内部,主文档找不到。解决:switch_to.frame()。
3在新窗口点击后开了新标签页,焦点还在旧窗口。解决:switch_to.window()。
4需要悬停元素是隐藏菜单,需鼠标移上去才显示。解决:ActionChains.move_to_element()。
5属性动态变化ID 或 Class 是随机生成的 (如 id="btn_123" )。解决:改用 XPath 模糊匹配或稳定属性。
6元素被遮挡有广告弹窗或透明层盖住了元素。解决:先关闭弹窗,或用 execute_script 强制点击。
7不在可视区元素在屏幕下方,未滚动到。解决:scrollIntoView 滚动。
8非标准下拉框不是 <select> 标签,而是 div+ul+li 模拟的。解决:直接用普通元素定位点击,不要用 Select 类。

13. 验证码处理方案 (Captcha Handling)

Selenium 无法直接识别图形验证码。根据项目阶段和验证码类型,通常采用以下 4 种策略:

方案 A:测试环境'万能码/后门' (⭐⭐⭐⭐⭐ 推荐)

场景:公司内部测试环境。 做法:联系开发人员,在测试环境设置一个'万能验证码'(如固定输入 8888 或 1234 即可通过),或者在代码中判断如果是测试账号则跳过验证逻辑。 优点:最稳定、执行最快、维护成本最低。 缺点:需要开发配合,生产环境不可用。

# 示例:测试环境固定验证码
if env == "test":
    code_input.send_keys("8888") # 开发约定的万能码
方案 B:Cookie 绕过法 (⭐⭐⭐⭐ 推荐)

场景:登录一次后,后续操作不需要重复登录。 做法:

  1. 手动登录一次成功网站。
  2. 获取浏览器的 Cookie (特别是包含用户身份信息的 Session ID)。
  3. 在自动化脚本启动浏览器后,先注入该 Cookie,然后刷新页面,直接处于'已登录'状态,跳过验证码步骤。

优点:无需识别验证码,模拟真实用户状态。 缺点:Cookie 有有效期,过期需重新获取;首次仍需人工或识别介入。

# 1. 打开首页
driver.get("http://example.com")

# 2. 添加 Cookie (格式需与浏览器一致)
driver.add_cookie({"name": "SESSION_ID", "value": "abc123xyz...", "domain": "example.com"})

# 3. 刷新页面生效
driver.refresh()
# 此时已自动登录,可直接操作内部页面
方案 C:第三方打码平台 (⭐⭐⭐ 通用方案)

场景:必须通过真实验证码,且无后门。 做法:调用第三方 OCR 识别平台 API(如:超级鹰、云打码、2Captcha 等)。 流程:截图验证码 -> 发送图片到平台 -> 平台返回识别结果 -> 填入输入框。 优点:能解决大多数常见图形验证码。 缺点:收费、有网络延迟、识别率非 100%、依赖外部服务稳定性。

# 伪代码示例 (以超级鹰为例)
from chaojiying import ChaojiyingClient

# 1. 截取验证码元素图片
element = driver.find_element(By.ID, "captcha_img")
element.screenshot("./code.png")

# 2. 调用第三方 API
client = ChaojiyingClient('用户名', '密码', '软件ID')
result = client.post_file(9004, './code.png') # 9004 代表验证码类型

# 3. 获取识别结果并输入
if result['ret'] == 0:
    code = result['pic_str']
    driver.find_element(By.ID, "captcha_input").send_keys(code)
else:
    print("识别失败")
方案 D:本地 OCR 库 (⭐⭐ 简单验证码)

场景:验证码非常简单(纯数字、无干扰线、字体清晰)。 做法:使用 tesseract-ocr (Python 库 pytesseract) 本地识别。 优点:免费、无需网络。 缺点:对复杂验证码(干扰线、扭曲、点选)识别率极低,配置环境麻烦。

import pytesseract
from PIL import Image

# 1. 截图
element.screenshot("./code.png")

# 2. 图片预处理 (去色、二值化等,提高识别率 - 需 OpenCV 配合)
# ... 预处理代码 ...

# 3. 识别
text = pytesseract.image_to_string(Image.open("./code.png"), lang='eng')
driver.find_element(By.ID, "captcha_input").send_keys(text.strip())

💡 核心建议:首选:找开发加测试后门(方案 A)。次选:Cookie 绕过(方案 B),适合登录后的大流程测试。最后手段:第三方打码(方案 C),仅在必须验证登录功能且无其他办法时使用。避免:不要试图用 Selenium 自己去'猜'或硬编码复杂的动态验证码。


💡 Selenium 核心操作与最佳实践终极速查表

场景分类推荐方法 / 核心类关键语法/注意点🏆 最佳实践建议
基础交互click(), send_keys(), clear()输入前建议先 clear() 清空旧值操作前先检查 is_displayed() 和 is_enabled(),确保元素可见且可用
状态断言element.text, is_selected(), is_enabled(), is_displayed()text 仅获取可见文本;is_系列返回布尔值不要只依赖 find_element 不报错,务必用 is_ 系列做逻辑判断
复杂鼠标ActionChains必须调用 .perform() 才会执行动作用于悬停 (Hover)、拖拽、右键;链式调用更清晰
原生弹窗driver.switch_to.alert必须先切换上下文才能操作 (accept(), dismiss())仅处理浏览器原生 Alert/Confirm/Prompt,非原生模态框需用普通定位
下拉菜单Select 类仅限<select> 标签 (select_by_visible_text 等)若是 div+ul 模拟的下拉框,直接使用普通元素定位点击,勿用 Select 类
滚动/JSdriver.execute_script()JS 是操作滚动条、修改属性的唯一途径优先用 scrollIntoView 滚动到元素;可用于移除 disabled 属性或强制点击
Frame 切换switch_to.frame(), switch_to.default_content()进得去必须出得来操作完嵌套页面后,务必立即调用 default_content() 切回主文档,避免后续定位失败
多窗口window_handles, switch_to.window()句柄是动态列表,需重新获取切换到新窗口操作完后,若需回主窗口,记得再次切换句柄
等待机制WebDriverWait + EC拒绝滥用 time.sleep(),慎用全局隐式等待首选显式等待 (精准控制),次选隐式等待,尽量避免强制等待以提高脚本稳定性
环境清理driver.quit()关闭所有窗口并结束驱动进程务必放在 finally 块或 tearDown 方法中,确保即使报错也能执行资源释放

目录

  1. 1. 元素本身属性操作
  2. 假设已定位到元素:element = driver.find_element(By.ID, "xxx")
  3. 1. 获取元素文本 (获取标签对之间的文本,不含 HTML 标签)
  4. 2. 判断元素是否被选中 (常用于单选框 radio、复选框 checkbox)
  5. 3. 判断元素是否可用 (未被 disabled 禁用)
  6. 4. 判断元素是否可见 (在页面上显示且宽高不为 0)
  7. 模拟点击:element.click()
  8. 模拟输入:element.send_keys()
  9. 模拟清除:element.clear()
  10. 页面刷新:driver.refresh()
  11. 2. 浏览器窗口操作
  12. 1. 最大化窗口
  13. 2. 刷新页面
  14. 3. 后退 (相当于点击浏览器后退按钮)
  15. 4. 前进 (相当于点击浏览器前进按钮)
  16. 5. 退出 (关闭所有关联窗口并结束驱动进程,务必在脚本末尾使用)
  17. 注意:driver.close() 仅关闭当前焦点窗口
  18. 3. 滚动条处理 (JavaScript 执行)
  19. 1. 定义 JS 字符串
  20. 方式 A: 滚动到绝对坐标 (x=横向,y=纵向)
  21. 方式 B: 滚动到底部
  22. 方式 C: 滚动到特定元素位置 (需先定位元素)
  23. element = driver.find_element(By.ID, "footer")
  24. jsscrollelem = "arguments[0].scrollIntoView();"
  25. 2. 执行 JS 代码
  26. 4. 截图处理
  27. 截取整个页面并保存为文件 (参数为文件路径,支持 .png)
  28. 或者获取二进制数据 (不保存文件,用于内存处理)
  29. imgdata = driver.getscreenshotaspng()
  30. 5. 多窗口/标签页切换
  31. 1. 获取所有窗口句柄 (列表形式)
  32. 2. 切换到指定窗口 (通过下标或具体句柄值)
  33. 切换到最新打开的窗口 (通常是列表最后一个)
  34. 切换到第一个窗口
  35. 3. (可选) 关闭当前窗口后切回主窗口
  36. driver.close()
  37. driver.switchto.window(driver.windowhandles[0])
  38. 6. Frame/Iframe 切换
  39. 1. 定位到 frame 元素
  40. 或者直接通过 ID/Name 字符串:driver.switchto.frame("loginframe")
  41. 2. 切换到该 frame (之后只能操作 frame 内部的元素)
  42. ... 执行内部元素操作 ...
  43. 3. 切回主文档 (默认内容),以便操作外部元素
  44. (可选) 切换到父级 frame (若嵌套多层)
  45. driver.switchto.parentframe()
  46. 7. 时间等待机制
  47. A. 强制等待 (不推荐作为主要手段)
  48. 程序暂停执行指定秒数,无论页面是否加载完成
  49. B. 隐式等待 (全局设置)
  50. 设置全局超时时间。若元素未立即出现,轮询查找直到超时。
  51. 只需设置一次,对后续所有 find_element 生效。
  52. C. 显式等待 (推荐,局部精准控制)
  53. 初始化等待对象:最大等待 10 秒,每 0.5 秒检查一次
  54. 场景 1: 等待元素可见 (推荐,确保元素不仅能找到,还能交互)
  55. 场景 2: 等待元素存在 (仅在 DOM 中,不一定可见)
  56. 场景 3: 等待元素可点击
  57. 场景 4: 自定义条件 (Lambda 表达式)
  58. 8. 鼠标与键盘操作
  59. 1. 初始化动作链
  60. 2. 鼠标悬停 (二级菜单常用)
  61. 先定位到父级菜单元素
  62. .perform() 必须调用以执行动作
  63. 3. 右键点击
  64. actions.context_click(element).perform()
  65. 4. 双击
  66. actions.double_click(element).perform()
  67. 5. 拖拽 (从源元素拖到目标元素)
  68. source = driver.find_element(By.ID, "drag")
  69. target = driver.find_element(By.ID, "drop")
  70. actions.draganddrop(source, target).perform()
  71. 6. 键盘组合键 (如:Ctrl+A 全选,Ctrl+C 复制)
  72. inputbox = driver.findelement(By.ID, "content")
  73. inputbox.sendkeys(Keys.CONTROL, "a") # 全选
  74. inputbox.sendkeys(Keys.CONTROL, "c") # 复制
  75. 9. 浏览器原生弹框处理
  76. 1. 切换到弹框
  77. 2. 获取弹框文本内容
  78. 3. 点击“确定” (接受)
  79. 4. 点击“取消” (解散,仅适用于 confirm/prompt)
  80. alert.dismiss()
  81. 5. 在 prompt 弹框中输入内容
  82. alert.send_keys("输入的内容")
  83. alert.accept()
  84. 10. 下拉框处理 (Select)
  85. 1. 定位到 select 元素
  86. 2. 通过可见文本选择
  87. 3. 通过 value 属性值选择
  88. 4. 通过索引选择 (从 0 开始)
  89. 5. 取消选择 (仅支持多选下拉框)
  90. dropdown.deselect_all()
  91. dropdown.deselectbyvisible_text("北京市")
  92. 6. 判断是否多选
  93. 11. 其他 JavaScript 高级用法
  94. 1. 移除元素的 disabled 属性 (强制启用按钮)
  95. btn = driver.findelement(By.ID, "submitbtn")
  96. driver.execute_script("arguments[0].removeAttribute('disabled')", btn)
  97. 2. 直接通过 JS 点击元素 (当 element.click() 被遮挡或失效时)
  98. driver.execute_script("arguments[0].click()", btn)
  99. 3. 修改输入框的值 (绕过某些监听事件限制)
  100. inputbox = driver.findelement(By.ID, "username")
  101. driver.executescript("arguments[0].value='admin'", inputbox)
  102. 4. 获取页面标题或当前 URL (通常直接用 driver.title / driver.current_url,但也可用 JS)
  103. title = driver.execute_script("return document.title")
  104. 12. 定位不到元素?排查清单 (Troubleshooting)
  105. 13. 验证码处理方案 (Captcha Handling)
  106. 方案 A:测试环境“万能码/后门” (⭐⭐⭐⭐⭐ 推荐)
  107. 示例:测试环境固定验证码
  108. 方案 B:Cookie 绕过法 (⭐⭐⭐⭐ 推荐)
  109. 1. 打开首页
  110. 2. 添加 Cookie (格式需与浏览器一致)
  111. 3. 刷新页面生效
  112. 此时已自动登录,可直接操作内部页面
  113. 方案 C:第三方打码平台 (⭐⭐⭐ 通用方案)
  114. 伪代码示例 (以超级鹰为例)
  115. 1. 截取验证码元素图片
  116. 2. 调用第三方 API
  117. 3. 获取识别结果并输入
  118. 方案 D:本地 OCR 库 (⭐⭐ 简单验证码)
  119. 1. 截图
  120. 2. 图片预处理 (去色、二值化等,提高识别率 - 需 OpenCV 配合)
  121. ... 预处理代码 ...
  122. 3. 识别
  123. 💡 Selenium 核心操作与最佳实践终极速查表

更多推荐文章

查看全部
  • 前端视角下的 Agent 工程化开发学习路线
  • 基于 SpringBoot 的宠物销售系统设计与实现
  • Spring Boot 3 RestClient 完整教程
  • AI Agent 安全漏洞与 Claude Code 编程范式转移
  • Unity+AI 一句话制作完整小游戏实战指南
  • Cursor 中配置与使用 MCP 服务实战指南
  • 基于大模型的自助式 AI 对话系统构建与应用
  • 豆包与扣子 Coze 对比:字节两大 AI 平台如何选择
  • LM Studio 模型加载指南:从格式识别到本地部署
  • IntelliJ IDEA 项目配置与 Web 部署指南
  • Linux 下部署 GraphRAG 并接入 Ollama 本地模型
  • NVIDIA Jetson Orin Nano 8GB 开发套件评测:边缘 AI 与性能对比
  • 前端请求后端 404/405/500 状态码排查与解决
  • Linux 容器化核心原理:Namespace 隔离与 cgroups 资源控制及 LXC 实战
  • Isaac Lab Cartpole 强化学习训练流程详解
  • ZeroClaw 轻量级 AI Agent 安装与使用指南
  • 深度生成模型对比:VAE、GAN、AR、Flow 与 Diffusion 原理及实现
  • 飞算 JavaAI 智能编程工具技术解析
  • Axios 错误处理进阶封装:实现网络层数据与状态解耦
  • Qwen3-4B CPU 环境部署避坑指南

相关免费在线工具

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online