Skip to content

源码教程:Cookie、存储与页面设置 ​

这一组命令最容易混淆作用域。任务的 Page 可以独立,但 BrowserContext 可能共享;修改上下文会影响多个任务。不能把所有 set 开头的命令都当作当前页设置。

命令实现
get_cookies调用 context.cookies,可按 URL 过滤;将 Cookie 对象转为字段列表并返回 count
set_cookie创建含 name、value 的 Cookie,按可选 url 设置作用域,再调用 addCookies
clear_cookies调用 context.clearCookies,清除共享上下文 Cookie,不是只清当前域名

当前 set_cookie 命令没有暴露 domain/path 等完整 Cookie 构造参数。实际使用应提供有效 URL;不能因为 url 在注册层可选就认为缺少作用域的 Cookie 一定能添加成功。

json
{"id":"1001","method":"set_cookie","params":{"name":"demo_preference","value":"compact","url":"https://example.com"}}

不要在公开示例中使用真实登录 Cookie。读取 Cookie 的返回属于账号数据,不能因为是只读操作就随意写入教程。

2. localStorage 由当前页面 origin 决定 ​

get_local_storage 在当前 Page 执行脚本:传 key 时读取单项,未传时返回整个 localStorage 的 JSON 字符串,放在 data.value。客户端若需要对象,应再解析该字符串,而不是假定 data.value 本身已经是对象。

set_local_storage 调用 localStorage.setItem;clear_local_storage 调用 localStorage.clear。它们作用于当前页面的 origin。共享上下文中,同源页签会看到同一份持久化数据;换到另一个域名后,读到的不是原站点数据。

不透明 origin 或受限制页面可能拒绝存储访问。先导航到需要测试的本地站点,不要在空白页上用失败结果判断存储实现坏了。

3. 设置命令的真实作用域 ​

命令调用对象实现和影响
set_viewportPagesetViewportSize,修改当前页 CSS 视口,返回 width/height
set_mediaPageemulateMedia,设置 light/dark/no-preference,不是操作系统主题
set_geolocationContext先授予 geolocation 权限,再设置经纬度
set_offlineContextsetOffline,影响共享上下文网络状态
set_headersContext解析 headersJson 为字符串映射,调用 setExtraHTTPHeaders
set_credentialsContext 创建配置HTTP 基本认证参数需要重建上下文,服务会检查任务数和启动方式

headersJson 是一个包含 JSON 文本的字符串,不是 params 内任意嵌套对象:

json
{"id":"1001","method":"set_headers","params":{"headersJson":"{\"X-Demo-Mode\":\"fixture\"}"}}

set_credentials 不是网站登录表单填用户名密码。当前实现只允许具备可重建配置、且没有其他任务会受影响时执行;CDP 接入路径可能没有可重建的持久上下文选项,会明确拒绝。

4. 验证与恢复 ​

使用两个同源页签和一个不同源页签测试 Cookie、localStorage 的共享边界。视口与主题测试则验证只改变当前 Page。设置离线、请求头或地理位置后记录原始配置,在测试结束恢复,避免影响后续任务。涉及真实共享 profile 时,不能把 clear_cookies 当作普通的无损重置。

注册参数与 Java 入口 ​

以下按 CommandTable 实际读取参数整理。* 表示注册层使用必填读取器;其余字段省略后由服务决定默认行为。带条件的入口仍需满足正文说明,例如上传文件来源、元素定位二选一。外层 id 不重复列出。

命令params 字段Java 入口
get_cookiesurlgetCookies
set_cookiename、value、urlsetCookie
clear_cookies无clearCookies
get_local_storagekeygetLocalStorage
set_local_storagekey*、valuesetLocalStorage
clear_local_storage无clearLocalStorage
set_viewportwidth、heightsetViewport
set_geolocationlatitude、longitudesetGeolocation
set_offlineofflinesetOffline
set_headersheadersJson*setHeaders
set_credentialsusername、passwordsetCredentials
set_mediacolorScheme*setMedia

当前源码:命令注册与执行 ​

先在本章上半部分理解行为,再按命令展开实现。注册代码说明 JSON 参数如何传给 Java;服务方法展示实际浏览器操作。方法依赖共享类中的字段和辅助函数,不应脱离原类直接粘贴编译。

get_cookies ​

展开参数注册

源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
    put("get_cookies", (svc, id, a) -> svc.getCookies(id, optStr(a, "url")));
展开 getCookies 实现

源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
  public RespBodyVo getCookies(Long browserId, String url) {
    BrowserInstance inst = INSTANCES.get(browserId);
    if (inst == null) {
      return notFound(browserId);
    }
    List<Cookie> cookies = (url == null || url.isEmpty()) ? inst.context.cookies() : inst.context.cookies(url);
    List<Kv> result = new ArrayList<>();
    for (Cookie cookie : cookies) {
      result.add(Kv.by("name", cookie.name).set("value", cookie.value).set("domain", cookie.domain)
          .set("path", cookie.path).set("expires", cookie.expires).set("httpOnly", cookie.httpOnly)
          .set("secure", cookie.secure).set("sameSite", cookie.sameSite == null ? null : cookie.sameSite.name()));
    }
    return RespBodyVo.ok(Kv.by("cookies", result).set("count", result.size()));
  }
展开参数注册

源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
    put("set_cookie", (svc, id, a) -> svc.setCookie(id, reqStr(a, "name"), reqStr(a, "value"), optStr(a, "url")));
展开 setCookie 实现

源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
  public RespBodyVo setCookie(Long browserId, String name, String value, String url) {
    BrowserInstance inst = INSTANCES.get(browserId);
    if (inst == null) {
      return notFound(browserId);
    }
    Cookie cookie = new Cookie(name, value);
    if (url != null && !url.isEmpty()) {
      cookie.setUrl(url);
    }
    try {
      inst.context.addCookies(Arrays.asList(cookie));
    } catch (PlaywrightException e) {
      return RespBodyVo.fail("set_cookie 失败:" + briefMessage(e.getMessage()));
    }
    return RespBodyVo.ok();
  }

clear_cookies ​

展开参数注册

源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
    put("clear_cookies", (svc, id, a) -> svc.clearCookies(id));
展开 clearCookies 实现

源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
  public RespBodyVo clearCookies(Long browserId) {
    BrowserInstance inst = INSTANCES.get(browserId);
    if (inst == null) {
      return notFound(browserId);
    }
    inst.context.clearCookies();
    return RespBodyVo.ok();
  }

get_local_storage ​

展开参数注册

源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
    put("get_local_storage", (svc, id, a) -> svc.getLocalStorage(id, optStr(a, "key")));
展开 getLocalStorage 实现

源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
  public RespBodyVo getLocalStorage(Long browserId, String key) {
    BrowserInstance inst = INSTANCES.get(browserId);
    if (inst == null) {
      return notFound(browserId);
    }
    try {
      Object value = inst.page.evaluate("(key) => key ? localStorage.getItem(key) : JSON.stringify(localStorage)",
          key == null ? "" : key);
      return RespBodyVo.ok(Kv.by("value", value));
    } catch (PlaywrightException e) {
      return RespBodyVo.fail("get_local_storage 失败:" + briefMessage(e.getMessage()));
    }
  }

set_local_storage ​

展开参数注册

源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
    put("set_local_storage", (svc, id, a) -> svc.setLocalStorage(id, reqStr(a, "key"), optStr(a, "value")));
展开 setLocalStorage 实现

源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
  public RespBodyVo setLocalStorage(Long browserId, String key, String value) {
    BrowserInstance inst = INSTANCES.get(browserId);
    if (inst == null) {
      return notFound(browserId);
    }
    try {
      inst.page.evaluate("([k, v]) => localStorage.setItem(k, v)", Arrays.asList(key, value));
      return RespBodyVo.ok();
    } catch (PlaywrightException e) {
      return RespBodyVo.fail("set_local_storage 失败:" + briefMessage(e.getMessage()));
    }
  }

clear_local_storage ​

展开参数注册

源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
    put("clear_local_storage", (svc, id, a) -> svc.clearLocalStorage(id));
展开 clearLocalStorage 实现

源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
  public RespBodyVo clearLocalStorage(Long browserId) {
    BrowserInstance inst = INSTANCES.get(browserId);
    if (inst == null) {
      return notFound(browserId);
    }
    try {
      inst.page.evaluate("() => localStorage.clear()");
      return RespBodyVo.ok();
    } catch (PlaywrightException e) {
      return RespBodyVo.fail("clear_local_storage 失败:" + briefMessage(e.getMessage()));
    }
  }

set_viewport ​

展开参数注册

源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
    put("set_viewport", (svc, id, a) -> svc.setViewport(id, reqInt(a, "width"), reqInt(a, "height")));
展开 setViewport 实现

源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
  public RespBodyVo setViewport(Long browserId, int width, int height) {
    BrowserInstance inst = INSTANCES.get(browserId);
    if (inst == null) {
      return notFound(browserId);
    }
    inst.page.setViewportSize(width, height);
    return RespBodyVo.ok(Kv.by("width", width).set("height", height));
  }

set_geolocation ​

展开参数注册

源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
    put("set_geolocation", (svc, id, a) -> svc.setGeolocation(id, reqDouble(a, "latitude"), reqDouble(a, "longitude")));
展开 setGeolocation 实现

源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
  public RespBodyVo setGeolocation(Long browserId, double latitude, double longitude) {
    BrowserInstance inst = INSTANCES.get(browserId);
    if (inst == null) {
      return notFound(browserId);
    }
    try {
      inst.context.grantPermissions(Arrays.asList("geolocation"));
      inst.context.setGeolocation(new Geolocation(latitude, longitude));
      return RespBodyVo.ok();
    } catch (PlaywrightException e) {
      return RespBodyVo.fail("set_geolocation 失败:" + briefMessage(e.getMessage()));
    }
  }

set_offline ​

展开参数注册

源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
    put("set_offline", (svc, id, a) -> svc.setOffline(id, optBool(a, "offline")));
展开 setOffline 实现

源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
  public RespBodyVo setOffline(Long browserId, boolean offline) {
    BrowserInstance inst = INSTANCES.get(browserId);
    if (inst == null) {
      return notFound(browserId);
    }
    inst.context.setOffline(offline);
    return RespBodyVo.ok(Kv.by("offline", offline));
  }

set_headers ​

展开参数注册

源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
    put("set_headers", (svc, id, a) -> svc.setHeaders(id, reqStr(a, "headersJson")));
展开 setHeaders 实现

源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
  public RespBodyVo setHeaders(Long browserId, String headersJson) {
    BrowserInstance inst = INSTANCES.get(browserId);
    if (inst == null) {
      return notFound(browserId);
    }
    try {
      JSONObject obj = JSON.parseObject(headersJson);
      Map<String, String> headers = new LinkedHashMap<>();
      for (String key : obj.keySet()) {
        headers.put(key, String.valueOf(obj.get(key)));
      }
      inst.context.setExtraHTTPHeaders(headers);
      return RespBodyVo.ok(Kv.by("headers", headers));
    } catch (Exception e) {
      return RespBodyVo.fail("set_headers 失败:" + briefMessage(e.getMessage()));
    }
  }

set_credentials ​

展开参数注册

源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
    put("set_credentials", (svc, id, a) -> svc.setCredentials(id, reqStr(a, "username"), reqStr(a, "password")));
展开 setCredentials 实现

源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
  public RespBodyVo setCredentials(Long browserId, String username, String password) {
    BrowserInstance inst = INSTANCES.get(browserId);
    if (inst == null) {
      return notFound(browserId);
    }
    if (inst.opts == null) {
      // opts 为空 = 这次浏览器是「自己拉进程 + CDP 接上」起来的(用户自己的 Chrome profile,或 Edge):
      // 这种上下文的创建参数不在我们手里,HTTP 认证凭据没地方设
      SharedBrowser shared = sharedBrowser;
      boolean edge = shared != null && shared.resolvedType.isEdge();
      return RespBodyVo.fail("set_credentials 失败:当前浏览器走的是「自己拉进程 + CDP 接入」这条启动路径("
          + (edge ? "browser=edge" : "用用户自己的 Chrome profile") + "),HTTP 认证凭据只能在 Playwright "
          + "创建上下文时设置,这条路径上没法重建上下文"
          + (edge ? ";需要 HTTP 基本认证时改用 browser=chrome 或 browser=chromium(托管 profile 那条路)" : ""));
    }
    if (INSTANCES.size() > 1) {
      return RespBodyVo.fail("set_credentials 会重建整个浏览器,而所有任务共用同一个浏览器与 profile;请先 close 掉其它任务再试");
    }
    inst.opts.setHttpCredentials(new HttpCredentials(username, password));
    restartContext(inst);
    return RespBodyVo.ok(Kv.by("restarted", true));
  }

set_media ​

展开参数注册

源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
    put("set_media", (svc, id, a) -> svc.setMedia(id, reqStr(a, "colorScheme")));
展开 setMedia 实现

源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。

java
  public RespBodyVo setMedia(Long browserId, String colorScheme) {
    BrowserInstance inst = INSTANCES.get(browserId);
    if (inst == null) {
      return notFound(browserId);
    }
    try {
      ColorScheme scheme = "dark".equalsIgnoreCase(colorScheme) ? ColorScheme.DARK
          : "light".equalsIgnoreCase(colorScheme) ? ColorScheme.LIGHT : ColorScheme.NO_PREFERENCE;
      inst.page.emulateMedia(new Page.EmulateMediaOptions().setColorScheme(scheme));
      return RespBodyVo.ok(Kv.by("colorScheme", scheme.name()));
    } catch (PlaywrightException e) {
      return RespBodyVo.fail("set_media 失败:" + briefMessage(e.getMessage()));
    }
  }