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

RuyiPage 本地存储

浏览器本地存储包括 localStorage、sessionStorage 和 Cookie。localStorage 持久保存,sessionStorage 随标签页关闭而清空。

核心概念

存储类型生命周期容量跨标签页
localStorage持久(手动清除)约 5-10MB同域共享
sessionStorage标签页关闭即清除约 5MB不共享
Cookie可设过期时间约 4KB/条同域共享

核心 API

page.run_js(操作 localStorage)

返回: str 或 None
page.run_js('localStorage.getItem(key)') / page.run_js('localStorage.setItem(key, value)', as_expr=False)

通过 JavaScript 读写 localStorage。RuyiPage 不内置 storage API,直接用 run_js 操作。

参数说明
参数说明
key/value存储键名和值。
常见坑
  • 页面必须已加载,about:blank 没有 localStorage。
相关示例

快速上手

python 读写 localStorage
from ruyipage import launch

page = launch()
try:
    page.get("https://example.com")

    # 写入 localStorage
    page.run_js(
        'localStorage.setItem("token", "my-secret-token")',
        as_expr=False
    )

    # 读取 localStorage
    token = page.run_js('localStorage.getItem("token")')
    print(f"Token: {token}")

    # 清空 localStorage
    page.run_js("localStorage.clear()", as_expr=False)
finally:
    page.quit()

相关示例源码

3 个示例 ▶ 点击展开

三标签页三隔离上下文:单浏览器多账号会话隔离

examples/37_three_isolated_user_context_tabs.py

展示单浏览器内三个标签页分别使用不同 user context,实现 Cookie 与存储完全隔离。

GitHub 仓库 查看仓库源码 page.browser_tools.create_user_contextpage.browser_tools.create_tabpage.browser_tools.remove_user_contextpage.contexts.close
  • 创建多个独立 user context
  • 在指定上下文中打开新标签页
  • 验证 Cookie 与存储隔离
  • 关闭标签页并清理上下文

Cookie 管理:读取、设置、过滤、删除

examples/08_cookies.py

围绕登录态和会话管理的核心示例。

GitHub 仓库 查看仓库源码 page.get_cookiespage.set_cookiespage.get_cookies_filteredpage.delete_cookiespage.browser.cookies
  • 读取服务端下发 Cookie
  • 通过 API 设置 Cookie
  • 按 name 等条件过滤 Cookie
  • 删除指定 Cookie 或清空全部 Cookie
  • 读取浏览器级 Cookie 视图

源码文件:app/content/ruyipage_examples/08_cookies.py · 仓库:08_cookies.py

python 注释版
# =============================
# RuyiPage 示例注释版
# 标题: Cookie 管理:读取、设置、过滤、删除
# 说明: 围绕登录态和会话管理的核心示例。
# 你会学到:
#   1. 读取服务端下发 Cookie
#   2. 通过 API 设置 Cookie
#   3. 按 name 等条件过滤 Cookie
#   4. 删除指定 Cookie 或清空全部 Cookie
#   5. 读取浏览器级 Cookie 视图
# 相关 API: page.get_cookies, page.set_cookies, page.get_cookies_filtered, page.delete_cookies, page.browser.cookies
# =============================

# -*- coding: utf-8 -*-
"""
示例8: Cookie管理
测试功能:
- 获取Cookie
- 设置Cookie
- 删除Cookie
- 清空所有Cookie
"""

import os
import sys
import io
import time

# 设置控制台输出编码为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__), ".."))
sys.path.insert(0, os.path.dirname(__file__))

from ruyipage import FirefoxPage, FirefoxOptions
from test_server import TestServer


def test_cookies():
    """测试Cookie管理功能"""
    print("=" * 60)
    print("测试8: Cookie管理")
    print("=" * 60)

    # 启动测试服务器
    server = TestServer(port=8888)
    server.start()

    opts = FirefoxOptions()
    opts.headless(False)
    page = FirefoxPage(opts)

    try:
        # 访问测试服务器的Cookie设置页面
        print("\n访问测试服务器...")
        page.get(server.get_url("/set-cookie"))
        page.wait(2)

        # 1. 获取服务器设置的Cookie
        print("\n1. 获取服务器设置的Cookie:")
        all_cookies = page.get_cookies(all_info=True)
        print(f"   共有 {len(all_cookies)} 个Cookie")
        for cookie in all_cookies:
            name = cookie.name
            value = cookie.value
            print(f"   - {name}: {value}")

        # 2. 通过API设置Cookie
        print("\n2. 通过API设置Cookie:")
        page.set_cookies(
            {
                "name": "api_cookie",
                "value": "api_value",
                "domain": "127.0.0.1",
                "path": "/",
            }
        )
        page.set_cookies(
            {"name": "user_id", "value": "12345", "domain": "127.0.0.1", "path": "/"}
        )
        print(f"   ✓ 已通过API设置2个Cookie")

        # 3. 验证Cookie已设置
        print("\n3. 验证Cookie已设置:")
        page.refresh()
        page.wait(1)
        all_cookies = page.get_cookies(all_info=True)
        print(f"   刷新后共有 {len(all_cookies)} 个Cookie")

        # 转换为字典方便查找
        cookies_dict = {}
        for c in all_cookies:
            cookies_dict[c.name] = c.value

        if "api_cookie" in cookies_dict:
            print(f"   ✓ api_cookie = {cookies_dict['api_cookie']}")
        if "user_id" in cookies_dict:
            print(f"   ✓ user_id = {cookies_dict['user_id']}")

        # 4. 设置带过期时间的Cookie
        print("\n4. 设置带过期时间的Cookie:")
        expire_time = int(time.time()) + 3600  # 1小时后过期
        page.set_cookies(
            {
                "name": "expire_cookie",
                "value": "will_expire",
                "domain": "127.0.0.1",
                "path": "/",
                "expiry": expire_time,
            }
        )
        print(f"   ✓ 已设置带过期时间的Cookie(1小时后过期)")

        # 5. 设置HttpOnly和Secure Cookie
        print("\n5. 设置HttpOnly和Secure Cookie:")
        page.set_cookies(
            {
                "name": "secure_cookie",
                "value": "secure_value",
                "domain": "127.0.0.1",
                "path": "/",
                "httpOnly": True,
                "secure": False,  # HTTP不能用secure=True
            }
        )
        print(f"   ✓ 已设置HttpOnly Cookie")

        # 6. 获取特定Cookie
        print("\n6. 获取特定Cookie:")
        all_cookies = page.get_cookies(all_info=True)
        cookies_dict = {}
        for c in all_cookies:
            cookies_dict[c.name] = c.value

        if "user_id" in cookies_dict:
            print(f"   user_id = {cookies_dict['user_id']}")
        if "expire_cookie" in cookies_dict:
            print(f"   expire_cookie = {cookies_dict['expire_cookie']}")

        # 6.1 简单 cookies 属性
        print("\n6.1 当前页面 cookies 属性:")
        simple_cookies = page.cookies
        print(f"   page.cookies 数量: {len(simple_cookies)}")

        # 6.2 setter 风格 Cookie API
        print("\n6.2 通过 page.set.cookies 设置Cookie:")
        page.set.cookies(
            {
                "name": "setter_cookie",
                "value": "setter_value",
                "domain": "127.0.0.1",
                "path": "/",
            }
        )
        page.wait(0.5)
        setter_cookies = {c.name: c.value for c in page.get_cookies()}
        print(f"   setter_cookie = {setter_cookies.get('setter_cookie')}")

        # 6.3 通过高层过滤 API 读取 Cookie
        print("\n6.3 通过高层过滤 API 读取Cookie:")
        filtered_cookies = page.get_cookies_filtered(name="user_id", all_info=True)
        print(f"   过滤结果数量: {len(filtered_cookies)}")
        if filtered_cookies:
            value = filtered_cookies[0].value
            print(f"   user_id(filtered) = {value}")

        # 7. 删除特定Cookie
        print("\n7. 删除特定Cookie:")
        page.delete_cookies(name="api_cookie")
        print(f"   ✓ 已删除 api_cookie")

        # 验证删除
        page.wait(0.5)
        all_cookies = page.get_cookies(all_info=True)
        cookies_dict = {}
        for c in all_cookies:
            cookies_dict[c.name] = c.value

        if "api_cookie" not in cookies_dict:
            print(f"   ✓ 确认 api_cookie 已被删除")
        else:
            print(f"   ⚠ api_cookie 仍然存在")

        # 7.1 通过公开删除接口删除 setter_cookie
        print("\n7.1 删除 setter_cookie:")
        page.delete_cookies(name="setter_cookie", domain="127.0.0.1")
        page.wait(0.5)
        cookies_after_remove = {c.name: c.value for c in page.get_cookies()}
        print(f"   setter_cookie 是否存在: {'setter_cookie' in cookies_after_remove}")

        # 8. 访问API验证Cookie发送
        print("\n8. 访问API验证Cookie发送:")
        page.get(server.get_url("/get-cookie"))
        page.wait(1)
        body_text = page.ele("tag:body").text
        print(f"   服务器收到的Cookie: {body_text[:100]}")

        # 9. 清空所有Cookie
        print("\n9. 清空所有Cookie:")
        page.delete_cookies()
        print(f"   ✓ 已清空所有Cookie")

        # 验证清空
        all_cookies = page.get_cookies()
        print(f"   清空后Cookie数量: {len(all_cookies)}")

        # 9.1 浏览器级 Cookie 读取
        print("\n9.1 浏览器级 cookies 读取:")
        browser_cookies = page.browser.cookies(all_info=False)
        print(f"   browser.cookies 数量: {len(browser_cookies)}")

        # 10. 重新设置并测试
        print("\n10. 重新设置Cookie并测试:")
        page.set_cookies(
            {
                "name": "final_cookie",
                "value": "final_value",
                "domain": "127.0.0.1",
                "path": "/",
            }
        )
        page.refresh()
        page.wait(1)

        all_cookies = page.get_cookies(all_info=True)
        cookies_dict = {}
        for c in all_cookies:
            cookies_dict[c.name] = c.value

        if "final_cookie" in cookies_dict:
            print(f"   ✓ final_cookie = {cookies_dict['final_cookie']}")
            print(f"   ✓ Cookie持久性测试通过")

        print("\n" + "=" * 60)
        print("✓ 所有Cookie管理测试通过!")
        print("=" * 60)

    except Exception as e:
        print(f"\n✗ 测试失败: {e}")
        import traceback

        traceback.print_exc()
    finally:
        page.wait(2)
        page.quit()
        server.stop()


if __name__ == "__main__":
    test_cookies()

Browser 模块:用户上下文与客户端窗口

examples/25_browser_user_context.py

Browser 模块最完整的 user context 与 client window 说明案例。

GitHub 仓库 查看仓库源码 page.browser_tools.get_user_contextspage.browser_tools.create_user_contextpage.browser_tools.remove_user_contextpage.browser_tools.create_tabpage.browser_tools.get_client_windowspage.browser_tools.set_window_state
  • 读取 user context 列表
  • 创建与删除 user context
  • 在指定 user context 中创建新 tab
  • 读取 client window 列表
  • 切换窗口状态为 minimized / maximized / fullscreen

源码文件:app/content/ruyipage_examples/25_browser_user_context.py · 仓库:25_browser_user_context.py

python 注释版
#!/usr/bin/env python
# =============================
# RuyiPage 示例注释版
# 标题: Browser 模块:用户上下文与客户端窗口
# 说明: Browser 模块最完整的 user context 与 client window 说明案例。
# 你会学到:
#   1. 读取 user context 列表
#   2. 创建与删除 user context
#   3. 在指定 user context 中创建新 tab
#   4. 读取 client window 列表
#   5. 切换窗口状态为 minimized / maximized / fullscreen
# 相关 API: page.browser_tools.get_user_contexts, page.browser_tools.create_user_context, page.browser_tools.remove_user_context, page.browser_tools.create_tab, page.browser_tools.get_client_windows, page.browser_tools.set_window_state
# =============================

# -*- coding: utf-8 -*-
"""示例25: Browser 模块(用户上下文 + 客户端窗口)严格结果版"""

import io
import sys
import time
from typing import Dict, List

if sys.platform == "win32":
    sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8")
    sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="utf-8")

from ruyipage import FirefoxPage


def add_result(
    results: List[Dict[str, str]], item: str, status: str, note: str
) -> None:
    """记录结构化结果。"""
    results.append({"item": item, "status": status, "note": note})


def print_results(results: List[Dict[str, str]]) -> None:
    """打印固定格式结果表。"""
    print("\n| 项目 | 状态 | 说明 |")
    print("| --- | --- | --- |")
    for row in results:
        print(f"| {row['item']} | {row['status']} | {row['note']} |")


def main() -> None:
    print("=" * 70)
    print("测试 25: Browser 用户上下文与窗口管理")
    print("=" * 70)

    page = FirefoxPage()
    results: List[Dict[str, str]] = []
    user_context_id = None
    new_tab_ctx = None

    try:
        page.get("https://www.example.com")

        # 1. user context 生命周期
        before = page.browser_tools.get_user_contexts()
        before_ids = [i.get("userContext") for i in before]
        add_result(
            results,
            "browser.getUserContexts before",
            "成功",
            f"创建前数量: {len(before)}",
        )

        user_context_id = page.browser_tools.create_user_context()
        if user_context_id:
            add_result(
                results,
                "browser.createUserContext",
                "成功",
                f"userContext={user_context_id}",
            )
        else:
            add_result(
                results, "browser.createUserContext", "失败", "未返回 userContext ID"
            )

        after_create = page.browser_tools.get_user_contexts()
        after_create_ids = [i.get("userContext") for i in after_create]
        if user_context_id in after_create_ids and len(after_create) == len(before) + 1:
            add_result(
                results,
                "browser.getUserContexts after create",
                "成功",
                f"数量变为 {len(after_create)}",
            )
        else:
            add_result(
                results,
                "browser.getUserContexts after create",
                "失败",
                "创建后数量或ID校验不通过",
            )

        if user_context_id:
            new_tab_ctx = page.browser_tools.create_tab(user_context=user_context_id)
            if new_tab_ctx:
                add_result(
                    results,
                    "browsingContext.create tab in user context",
                    "成功",
                    f"context={new_tab_ctx}",
                )
            else:
                add_result(
                    results,
                    "browsingContext.create tab in user context",
                    "失败",
                    "未返回新 tab context",
                )

        if new_tab_ctx:
            try:
                page.contexts.close(new_tab_ctx)
                add_result(
                    results, "browsingContext.close new tab", "成功", "新 tab 已关闭"
                )
                new_tab_ctx = None
            except Exception as e:
                add_result(
                    results, "browsingContext.close new tab", "跳过", str(e)[:120]
                )

        if user_context_id:
            page.browser_tools.remove_user_context(user_context_id)
            add_result(
                results,
                "browser.removeUserContext",
                "成功",
                f"已删除 {user_context_id}",
            )

            after_remove = page.browser_tools.get_user_contexts()
            after_remove_ids = [i.get("userContext") for i in after_remove]
            if user_context_id not in after_remove_ids and len(after_remove) == len(
                before_ids
            ):
                add_result(
                    results,
                    "browser.getUserContexts after remove",
                    "成功",
                    f"数量回到 {len(after_remove)}",
                )
            else:
                add_result(
                    results,
                    "browser.getUserContexts after remove",
                    "失败",
                    "删除后数量或ID校验不通过",
                )
            user_context_id = None

        # 2. client window 状态流
        windows = page.browser_tools.get_client_windows()
        if not windows:
            add_result(
                results, "browser.getClientWindows", "失败", "未返回任何 client window"
            )
        else:
            add_result(
                results, "browser.getClientWindows", "成功", f"窗口数量: {len(windows)}"
            )
            win = windows[0]
            win_id = win.get("clientWindow")
            states = ["minimized", "normal", "maximized", "fullscreen", "normal"]
            state_notes = []
            state_failed = False
            for state in states:
                page.browser_tools.set_window_state(win_id, state=state)
                time.sleep(0.4)
                current_windows = page.browser_tools.get_client_windows()
                current = current_windows[0] if current_windows else {}
                current_state = current.get("state")
                state_notes.append(f"{state}->{current_state}")
                if current_state != state:
                    state_failed = True

            if state_failed:
                add_result(
                    results,
                    "browser.setClientWindowState",
                    "失败",
                    ", ".join(state_notes),
                )
            else:
                add_result(
                    results,
                    "browser.setClientWindowState",
                    "成功",
                    ", ".join(state_notes),
                )

        print_results(results)

    except Exception as e:
        add_result(results, "示例执行", "失败", str(e)[:120])
        print_results(results)
        raise
    finally:
        if new_tab_ctx:
            try:
                page.contexts.close(new_tab_ctx)
            except Exception:
                pass
        if user_context_id:
            try:
                page.browser_tools.remove_user_context(user_context_id)
            except Exception:
                pass
        try:
            page.quit()
        except Exception:
            pass


if __name__ == "__main__":
    main()