page.wait
返回: Nonepage.wait(seconds)固定时间等待。简单但不推荐大量使用——应优先用条件等待。
参数说明
| 参数 | 说明 |
|---|---|
| seconds | 等待秒数,支持小数如 0.5。 |
常见坑
- 大量 sleep 会拖慢脚本且降低稳定性。
相关示例
等待机制决定脚本成功率。固定 sleep 只是兜底,真正稳定的脚本靠导航等待和元素等待。
page.wait(seconds)固定时间等待。简单但不推荐大量使用——应优先用条件等待。
| 参数 | 说明 |
|---|---|
| seconds | 等待秒数,支持小数如 0.5。 |
page.get(url, wait='complete')导航内建等待,是第一层稳定器。complete 等 readyState,none 立即返回。
| 参数 | 说明 |
|---|---|
| wait | 'complete'(推荐默认)/ 'interactive' / 'none'。 |
page.wait.ele(locator, timeout=10)等待元素出现在 DOM 中。适合等待异步加载的内容。
| 参数 | 说明 |
|---|---|
| locator | 与 ele() 相同的定位器。 |
| timeout | 超时秒数。 |
| 方式 | 用途 | 推荐程度 |
|---|---|---|
| page.get(wait='complete') | 等待页面加载完成 | 默认首选 |
| page.wait.ele(locator) | 等待特定元素出现 | 动态页面推荐 |
| page.wait(seconds) | 固定等待 | 仅用于兜底 |
from ruyipage import launch
page = launch()
try:
# 第一层:导航等待
page.get("https://example.com") # 默认等 readyState=complete
# 第二层:元素等待(异步内容)
result = page.wait.ele("css:#dynamic-content", timeout=10)
if result:
print(f"内容已加载: {result.text}")
else:
print("超时,内容未加载")
# 兜底:固定等待(尽量少用)
page.wait(0.5)
finally:
page.quit()用于建立稳定脚本的等待心智,比硬编码 sleep 更适合文档新手章节。
源码文件:app/content/ruyipage_examples/04_wait_conditions.py · 仓库:04_wait_conditions.py
# =============================
# RuyiPage 示例注释版
# 标题: 等待条件:出现、显示、隐藏、删除与页面就绪
# 说明: 用于建立稳定脚本的等待心智,比硬编码 sleep 更适合文档新手章节。
# 你会学到:
# 1. 等待元素出现
# 2. 等待元素可见
# 3. 等待异步内容显示
# 4. 等待元素隐藏或被删除
# 5. 等待标题变化或文档加载完成
# 相关 API: page.wait.ele, page.wait.ele_displayed, page.wait.ele_hidden, page.wait.ele_deleted, page.wait.title_contains, page.wait.doc_loaded
# =============================
# -*- coding: utf-8 -*-
"""
示例4: 等待条件
测试功能:
- 等待元素出现
- 等待元素可见
- 等待元素隐藏
- 等待元素删除
- 等待标题变化
- 等待URL变化
"""
import os
import sys
import io
# 设置控制台输出编码为UTF-8(Windows兼容)
if sys.platform == 'win32':
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
from ruyipage import FirefoxPage, FirefoxOptions
def test_wait_conditions():
"""测试等待条件功能"""
print("=" * 60)
print("测试4: 等待条件")
print("=" * 60)
opts = FirefoxOptions()
opts.headless(False)
page = FirefoxPage(opts)
try:
# 加载测试页面
test_page = os.path.join(os.path.dirname(__file__), 'test_pages', 'test_page.html')
test_url = 'file:///' + os.path.abspath(test_page).replace('\\', '/')
page.get(test_url)
page.wait(1)
# 1. 等待元素出现(已存在的元素)
print("\n1. 等待元素出现:")
elem = page.wait.ele('#main-title', timeout=5)
if elem:
print(f" ✓ 元素已找到: {elem.text}")
else:
print(f" ✗ 元素未找到")
# 2. 等待元素可见
print("\n2. 等待元素可见:")
btn = page.wait.ele_displayed('#click-btn', timeout=5)
if btn:
print(f" ✓ 按钮可见")
else:
print(f" ✗ 按钮不可见")
# 3. 触发延迟显示内容
print("\n3. 等待延迟显示的内容:")
show_btn = page.ele('text:显示延迟内容')
show_btn.click_self()
print(f" 已点击按钮,等待内容显示...")
# 等待动态内容出现
dynamic_elem = page.wait.ele_displayed('#dynamic-content', timeout=5)
if dynamic_elem:
print(f" ✓ 延迟内容已显示: {dynamic_elem.text}")
else:
print(f" ✗ 延迟内容未显示")
# 4. 等待元素隐藏
print("\n4. 等待元素隐藏:")
hide_btn = page.ele('text:隐藏内容')
hide_btn.click_self()
print(f" 已点击隐藏按钮...")
is_hidden = page.wait.ele_hidden('#dynamic-content', timeout=3)
if is_hidden:
print(f" ✓ 元素已隐藏")
else:
print(f" ✗ 元素仍然可见")
# 5. 等待元素删除
print("\n5. 等待元素从DOM删除:")
remove_btn = page.ele('text:删除内容')
remove_btn.click_self()
print(f" 已点击删除按钮...")
is_deleted = page.wait.ele_deleted('#dynamic-content', timeout=3)
if is_deleted:
print(f" ✓ 元素已从DOM删除")
else:
print(f" ✗ 元素仍在DOM中")
# 6. 等待标题包含特定文本
print("\n6. 等待标题包含特定文本:")
current_title = page.title
print(f" 当前标题: {current_title}")
result = page.wait.title_contains('RuyiPage', timeout=2)
if result:
print(f" ✓ 标题包含'RuyiPage'")
else:
print(f" ✗ 标题不包含'RuyiPage'")
# 7. 简单等待(暂停)
print("\n7. 简单等待2秒:")
page.wait(2)
print(f" ✓ 等待完成")
# 8. 等待页面加载完成
print("\n8. 等待页面加载完成:")
page.wait.doc_loaded(timeout=5)
print(f" ✓ 页面已加载完成")
# 9. 添加新内容并等待
print("\n9. 添加新内容并等待:")
add_btn = page.ele('text:添加内容')
add_btn.click_self()
page.wait(0.5)
# 等待新内容出现
new_content = page.wait.ele('#content-container .result', timeout=3)
if new_content:
print(f" ✓ 新内容已添加: {new_content.text}")
else:
print(f" ✗ 新内容未找到")
print("\n" + "=" * 60)
print("✓ 所有等待条件测试通过!")
print("=" * 60)
except Exception as e:
print(f"\n✗ 测试失败: {e}")
import traceback
traceback.print_exc()
finally:
page.wait(2)
page.quit()
if __name__ == '__main__':
test_wait_conditions()
最适合展示'一个真实业务脚本长什么样'的综合案例。
源码文件:app/content/ruyipage_examples/15_comprehensive.py · 仓库:15_comprehensive.py
# =============================
# RuyiPage 示例注释版
# 标题: 综合实战:表单填写、数据提取、动态内容、截图与状态验证
# 说明: 最适合展示'一个真实业务脚本长什么样'的综合案例。
# 你会学到:
# 1. 完整填写表单
# 2. 提交并验证页面反馈
# 3. 抽取表格数据
# 4. 处理动态新增内容
# 5. 对关键区域截图
# 相关 API: page.ele, page.eles, input, click_self, select.by_value, page.wait.ele_displayed, ele.screenshot, page.screenshot
# =============================
# -*- coding: utf-8 -*-
"""
示例15: 综合测试 - 实战场景
测试功能:
- 模拟真实的网页自动化场景
- 综合运用多种功能
- 表单填写和提交
- 数据提取
"""
import os
import sys
import io
# 设置控制台输出编码为UTF-8(Windows兼容)
if sys.platform == "win32":
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8")
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="utf-8")
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from ruyipage import FirefoxPage, FirefoxOptions
def test_comprehensive():
"""综合测试 - 实战场景"""
print("=" * 60)
print("测试15: 综合测试 - 实战场景")
print("=" * 60)
opts = FirefoxOptions()
opts.headless(False)
page = FirefoxPage(opts)
try:
# 加载测试页面
test_page = os.path.join(
os.path.dirname(__file__), "test_pages", "test_page.html"
)
test_url = "file:///" + os.path.abspath(test_page).replace("\\", "/")
page.get(test_url)
page.wait(1)
print("\n场景1: 填写并提交表单")
print("-" * 40)
# 1. 填写文本输入框
print("1. 填写表单字段...")
page.ele("#text-input").input("张三")
page.ele("#email-input").input("[email protected]")
page.ele("#password-input").input("password123")
page.ele("#number-input").input("25")
page.ele("#textarea").input("这是一段测试文本\n包含多行内容")
# 2. 选择复选框
page.ele("#checkbox1").click_self()
page.ele("#checkbox2").click_self()
# 3. 选择单选框
page.ele("#radio1").click_self()
# 4. 选择下拉框
select_ele = page.ele("#select-single")
select_ok = select_ele.select.by_value("opt2", mode="native_only")
if not select_ok:
select_ok = select_ele.select.by_value("opt2", mode="compat")
page.wait(0.5)
print(" ✓ 表单填写完成")
# 5. 提交表单
print("2. 提交表单...")
page.ele("#submit-btn").click_self()
page.wait(1)
# 6. 验证提交结果
result = page.ele("#form-result").text
print(f" 提交结果: {result[:100]}...")
print("\n场景2: 数据提取")
print("-" * 40)
# 7. 提取表格数据
print("1. 提取表格数据...")
table_rows = page.eles("#data-table tbody tr")
print(f" 表格共有 {len(table_rows)} 行数据")
table_data = []
for row in table_rows:
cells = row.eles("tag:td")
if len(cells) >= 4:
row_data = {
"id": cells[0].text,
"name": cells[1].text,
"age": cells[2].text,
"city": cells[3].text,
}
table_data.append(row_data)
print(f" - {row_data}")
print("\n场景3: 动态交互")
print("-" * 40)
# 8. 测试动态内容
print("1. 触发延迟显示...")
page.ele("text:显示延迟内容").click_self()
dynamic_elem = page.wait.ele_displayed("#dynamic-content", timeout=5)
if dynamic_elem:
print(f" ✓ 延迟内容已显示: {dynamic_elem.text}")
# 9. 添加多个内容
print("2. 添加多个动态内容...")
for i in range(3):
page.ele("text:添加内容").click_self()
page.wait(0.3)
new_items = page.eles("#content-container .result")
print(f" ✓ 已添加 {len(new_items)} 个新内容")
print("\n场景4: 页面截图")
print("-" * 40)
# 10. 截取关键区域
print("1. 截取关键区域...")
output_dir = os.path.join(os.path.dirname(__file__), "output", "comprehensive")
os.makedirs(output_dir, exist_ok=True)
# 表单区域截图
try:
form_section = page.ele("#form-section")
page.scroll.to_see(form_section)
page.wait(0.5)
form_section.screenshot(os.path.join(output_dir, "form_filled.png"))
print(f" ✓ 表单截图已保存")
except Exception as e:
print(f" ⚠ 表单截图跳过: {str(e)[:50]}")
# 表格截图
try:
table = page.ele("#data-table")
page.scroll.to_see(table)
page.wait(0.5)
table.screenshot(os.path.join(output_dir, "table_data.png"))
print(f" ✓ 表格截图已保存")
except Exception as e:
print(f" ⚠ 表格截图跳过: {str(e)[:50]}")
# 整页截图
page.screenshot(os.path.join(output_dir, "full_page.png"))
print(f" ✓ 整页截图已保存")
print("\n场景5: 多次交互")
print("-" * 40)
# 11. 连续点击测试
print("1. 连续点击按钮...")
click_btn = page.ele("#click-btn")
for i in range(5):
click_btn.click_self()
page.wait(0.2)
result = page.ele("#click-result").text
print(f" 点击结果: {result}")
# 12. 鼠标悬停测试
print("2. 鼠标悬停测试...")
hover_target = page.ele("#hover-target")
hover_target.hover()
page.wait(0.5)
hover_result = page.ele("#hover-result").text
print(f" 悬停结果: {hover_result}")
# 12.1 isTrusted 行为验证
print("3. isTrusted 行为验证...")
page.ele("#click-btn").click_self()
page.wait(0.2)
page.ele("#text-input").input("T", clear=False)
page.wait(0.2)
hover_target.hover()
page.wait(0.2)
print(f" click isTrusted: {page.is_trusted('click')}")
print(f" keydown isTrusted: {page.is_trusted('keydown')}")
print(f" mouseenter isTrusted: {page.is_trusted('mouseenter')}")
print("\n场景6: 数据验证")
print("-" * 40)
# 13. 验证元素状态
print("1. 验证元素状态...")
disabled_btn = page.ele("#disabled-btn")
print(f" 禁用按钮是否可用: {disabled_btn.is_enabled}")
print(f" 禁用按钮是否显示: {disabled_btn.is_displayed}")
# 14. 验证输入值
print("2. 验证输入值...")
text_value = page.ele("#text-input").value
email_value = page.ele("#email-input").value
print(f" 文本输入框: {text_value}")
print(f" 邮箱输入框: {email_value}")
# 15. 验证选择状态
print("3. 验证选择状态...")
checkbox1_checked = page.ele("#checkbox1").is_checked
radio1_checked = page.ele("#radio1").is_checked
print(f" 复选框1选中: {checkbox1_checked}")
print(f" 单选框1选中: {radio1_checked}")
print("\n" + "=" * 60)
print("✓ 综合测试全部通过!")
print(f"截图保存在: {output_dir}")
print("=" * 60)
except Exception as e:
print(f"\n✗ 测试失败: {e}")
import traceback
traceback.print_exc()
finally:
page.wait(3)
page.quit()
if __name__ == "__main__":
test_comprehensive()