mcpField
K
kernel-python-sdk

kernel-python-sdk

github.com/kernel开发13359 次安装2 周前更新
代码仓库

关于 kernel-python-sdk

面向使用 Kernel 管理浏览器会话的 Python 开发者技能,涵盖服务端 Playwright、CDP、配置文件、代理和会话清理。

主要功能

  1. 01服务端 Playwright 执行
  2. 02客户端通过 CDP 使用 Playwright
  3. 03持久化浏览器配置文件
  4. 04显式代理路由
  5. 05浏览器会话生命周期指引

适用场景

  1. 01在浏览器 VM 中运行 Playwright
  2. 02使用本地 Playwright 工具调试
  3. 03保留 Cookie 和配置文件状态
  4. 04通过代理路由会话

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/kernel/skills --skill kernel-python-sdk

安装后在 Claude Code 中输入/kernel-python-sdk确认已加载。

附带文件examples/examples.md

详细介绍

适用场景

使用此技能编写用于创建和控制 Kernel 浏览器会话的 Python 代码。以下场景优先使用此技能:

  • 在浏览器 VM 中运行服务端 Playwright
  • 通过 CDP 使用客户端 Playwright
  • 使用持久化配置文件和显式代理路由
  • 浏览器池或已部署的 Python 操作

使用 kernel-cli 技能执行 Shell 命令和快速的一次性会话。

设置

uv pip install -U kernel
# Add this only for client-side CDP:
uv pip install playwright

在环境中设置 KERNEL_API_KEY;不要将其写入源代码。Kernel() 和 AsyncKernel() 会自动读取它。始终使用异步客户端——不要在异步操作中调用同步 SDK 方法。

选择自动化路径

服务端 Playwright(默认)

在 Chrome 旁运行 JavaScript/TypeScript。这样可以避免本地 CDP 往返,也不需要本地 Playwright:

from kernel import Kernel

with Kernel() as client:
    browser = client.browsers.create(stealth=True, timeout_seconds=300)
    try:
        response = client.browsers.playwright.execute(
            browser.session_id,
            code="""
await page.goto("https://example.com");
return { title: await page.title(), url: page.url() };
""",
            timeout_sec=60,
        )
        if not response.success:
            raise RuntimeError(response.error or response.stderr or "Playwright execution failed")
        print(response.result)
    finally:
        client.browsers.delete_by_id(browser.session_id)

将会话 ID 作为第一个位置参数传入。代码会收到 page、context 和 browser。请使用 return;否则 response.result 为空。timeout_sec 限制远程代码执行时间,而 SDK 的 timeout= 选项控制 HTTP 请求。

通过 CDP 使用客户端 Playwright

需要本地 Playwright 工具或交互式调试时,使用 CDP:

import asyncio

from kernel import AsyncKernel
from playwright.async_api import async_playwright


async def main() -> None:
    async with AsyncKernel() as client:
        kernel_browser = await client.browsers.create(
            stealth=True,
            timeout_seconds=300,
        )
        try:
            async with async_playwright() as playwright:
                remote = await playwright.chromium.connect_over_cdp(
                    kernel_browser.cdp_ws_url
                )
                context = remote.contexts[0]
                page = context.pages[0] if context.pages else await context.new_page()
                await page.goto("https://example.com")
                print(await page.title())
        finally:
            await client.browsers.delete_by_id(kernel_browser.session_id)


asyncio.run(main())

复用现有默认上下文,以便页面能看到 Kernel 会话已加载的配置文件状态;新的隐身上下文不会共享该状态。SDK 客户端上下文会关闭 HTTP 连接,但不会代替删除远程浏览器。

浏览器生命周期和清理

  • 每次创建或获取会话后,立即用 try/finally 包裹。
  • 使用 client.browsers.delete_by_id(session_id) 删除普通会话;使用 AsyncKernel 时请加上 await。
  • 通过浏览器池获取的会话,应使用浏览器池释放 API 释放,而不是删除。
  • 即使有清理逻辑,也应将浏览器不活动超时设为有限值。活动操作可能延长该超时,因此它不能代替显式清理。
  • 只有在所有使用临时配置文件和代理的会话都结束后,才删除这些配置文件和代理。保留有意设置的持久化配置文件。

配置文件

先创建配置文件,再附加使用。需要将 Cookie 和本地状态持久化回配置文件时,设置 save_changes=True:

profile = client.profiles.create(name="checkout-login")
browser = client.browsers.create(
    profile={"id": profile.id, "save_changes": True},
    stealth=True,
)
try:
    # Automate with server-side Playwright or CDP.
    ...
finally:
    client.browsers.delete_by_id(browser.session_id)

删除浏览器会结束会话,并允许配置文件更改最终写入。不要先删除配置文件。使用 {"id": ...} 或 {"name": ...} 其中之一,不要同时使用。

Python SDK 可以请求任一归档格式,并原生重命名配置文件:

archive = client.profiles.download(profile.id, format="tar")
archive.write_to_file("profile.tar")
client.profiles.update(profile.id, name="checkout-login-v2")

SDK 会为 tar.zst 和 tar 两种格式写入归档;它不会解压归档内容。需要将归档解压到目录时,使用 kernel profiles download <id-or-name> --to ./profile。

代理和默认隐身代理

创建时使用 proxy_id 附加显式代理:

proxy = client.proxies.create(
    type="datacenter",
    config={"country": "US"},
    name="automation-us",
)
try:
    client.proxies.check(proxy.id, url="https://example.com")
    browser = client.browsers.create(stealth=True, proxy_id=proxy.id)
    try:
        ...
    finally:
        client.browsers.delete_by_id(browser.session_id)
finally:
    client.proxies.delete(proxy.id)  # Only if this proxy was created for this run.

针对特定目标的代理检查会验证该公共 HTTP/HTTPS URL。对于住宅和移动代理,此检查不能保证浏览器之后会使用相同的出口节点;对于自定义 URL,此检查也不会更新常规代理健康状态。

可以更改运行中浏览器的代理路由:

client.browsers.update(browser.session_id, proxy_id=another_proxy_id)
client.browsers.update(browser.session_id, proxy_id="")  # Remove explicit proxy.

未附加显式代理时,隐身浏览器可能会使用 Kernel 的默认隐身代理。可单独控制此代理:

client.browsers.update(browser.session_id, disable_default_proxy=True)   # Direct connection
client.browsers.update(browser.session_id, disable_default_proxy=False)  # Re-enable default

disable_default_proxy 是更新参数,不是浏览器创建参数。当前 SDK 不支持重命名代理;请使用 kernel proxies update <id> --name <new-name>。要更改代理名称以外的任何内容,请重新创建代理。

已部署操作模式

from typing import TypedDict

import kernel

app = kernel.App("app-name")


class TaskInput(TypedDict):
    task: str


@app.action("action-name")
async def run(ctx: kernel.KernelContext, payload: TaskInput):
    async with kernel.AsyncKernel() as client:
        browser = await client.browsers.create(
            invocation_id=ctx.invocation_id,
            timeout_seconds=300,
        )
        try:
            response = await client.browsers.playwright.execute(
                browser.session_id,
                code="return await page.title();",
            )
            if not response.success:
                raise RuntimeError(response.error or response.stderr or "Playwright execution failed")
            return response.result
        finally:
            await client.browsers.delete_by_id(browser.session_id)

二进制结果

服务端截图和 PDF 可能会返回 Node.js Buffer 形状的结果:

response = client.browsers.playwright.execute(
    browser.session_id,
    code="return await page.screenshot({ fullPage: true });",
)
if response.success and response.result:
    with open("output.png", "wb") as file:
        file.write(bytes(response.result["data"]))

参考资料

评论

支持 Markdown