全球动态代理 · 静态住宅代理 · 极高质量 · 包月不限量 · 学员低价 · 联系如意进行免费测试 · 欢迎公司及学员采购 · 另有任何海外数据采集需求,随时联系 · 商务合作微信:Charleval
Automation / 等待机制
RuyiPage Docs

RuyiPage 等待机制

等待机制决定脚本成功率。固定 sleep 只是兜底,真正稳定的脚本靠导航等待和元素等待。

核心 API

page.wait

返回: None
page.wait(seconds)

固定时间等待。简单但不推荐大量使用——应优先用条件等待。

参数说明
参数说明
seconds等待秒数,支持小数如 0.5。
常见坑
  • 大量 sleep 会拖慢脚本且降低稳定性。
相关示例

page.get(wait=)

返回: None
page.get(url, wait='complete')

导航内建等待,是第一层稳定器。complete 等 readyState,none 立即返回。

参数说明
参数说明
wait'complete'(推荐默认)/ 'interactive' / 'none'。
常见坑
  • wait='none' 后必须补充元素等待或 sleep。
相关示例

等待策略对比

方式用途推荐程度
page.get(wait='complete')等待页面加载完成默认首选
page.wait.ele(locator)等待特定元素出现动态页面推荐
page.wait(seconds)固定等待仅用于兜底

快速上手

python 实际中的等待组合
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()

注意事项

  • 优先用导航等待(page.get 的 wait 参数),覆盖 80% 的场景。
  • 异步内容用 page.wait.ele() 等待特定元素出现。
  • page.wait(seconds) 作为最后兜底,不要到处用。
  • 超时时间根据网络环境调整,慢网建议 15-30 秒。

相关示例源码

2 个示例 ▶ 点击展开

等待条件:出现、显示、隐藏、删除与页面就绪

examples/04_wait_conditions.py

用于建立稳定脚本的等待心智,比硬编码 sleep 更适合文档新手章节。

GitHub 仓库 查看仓库源码 page.wait.elepage.wait.ele_displayedpage.wait.ele_hiddenpage.wait.ele_deletedpage.wait.title_containspage.wait.doc_loaded
  • 等待元素出现
  • 等待元素可见
  • 等待异步内容显示
  • 等待元素隐藏或被删除
  • 等待标题变化或文档加载完成

源码文件:app/content/ruyipage_examples/04_wait_conditions.py · 仓库:04_wait_conditions.py

python 注释版
# =============================
# 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()

综合实战:表单填写、数据提取、动态内容、截图与状态验证

examples/15_comprehensive.py

最适合展示'一个真实业务脚本长什么样'的综合案例。

GitHub 仓库 查看仓库源码 page.elepage.elesinputclick_selfselect.by_valuepage.wait.ele_displayedele.screenshotpage.screenshot
  • 完整填写表单
  • 提交并验证页面反馈
  • 抽取表格数据
  • 处理动态新增内容
  • 对关键区域截图
  • 验证状态变化与 isTrusted

源码文件:app/content/ruyipage_examples/15_comprehensive.py · 仓库:15_comprehensive.py

python 注释版
# =============================
# 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()