Skip to main content

my-readurl-kit

my-readurl-kit 是一个独立的 Python 网页读取与内容提取库。当前的 read_url 实现迁移自 gede/gede/llm/tools/read_url_tool.py,但不依赖 gede 本身。

目标

  • 获取给定 URL 的页面内容,支持返回原始 HTML 或可读文本。
  • 通过 my-llmkit 非流式调用 LLM,提取正文或与查询相关的内容。
  • 同一套核心能力既可作为 Python 函数库使用,也可通过 CLI、MCP server 和 HTTP server 调用。
  • 将抓取、解析、LLM 提取和传输协议分层,避免任一入口绑死核心库。

当前 Python API

网络 I/O 使用异步 API,成功结果通过 ReadUrlResult 返回;请求、状态码、响应 大小和内容类型错误会抛出 ReadUrlError 的具体子类,不会伪装成普通内容字符串。

import asyncio

from my_readurl_kit import read_url


async def main() -> None:
    result = await read_url("https://example.com")
    print(result.content)
    print(result.final_url, result.status_code)


asyncio.run(main())

output_format 支持以下取值:

行为
raw 返回解码后的原始响应正文,适用于 HTML、JSON 和 JavaScript
text 使用 BeautifulSoup 将 HTML 转为规范化纯文本,也是默认值
body 通过 LLM 提取正文并剔除作者来源、推荐等非正文内容
relevant 通过 LLM 提取与 query 直接相关的完整原文段落

relevant 传入非空 query 时提取相关段落;未传入或仅传入空白 query 时等同于 body。其他模式会忽略 querybodyrelevant 只有在实际使用时才需要 LLM 配置;rawtext 不会创建或调用模型客户端。

调用方可以注入 httpx.AsyncClient、请求头和超时。默认跟随最多 10 次重定向, 接受文本、JSON、JavaScript 或 XML 响应,并将解压后的响应正文限制为 5 MiB。

成功抓取的原始页面及其响应元数据会按请求 URL 缓存,因而同一 URL 的后续读取不会 再次发起网络请求;HTML 解析和 LLM 提取仍会按每次调用执行。缓存默认存放在 /tmp/my-readurl-kit/caches,也可以通过 MY_READURL_KIT_CACHE_DIR 修改位置:

export MY_READURL_KIT_CACHE_DIR="/path/to/readurl-cache"

缓存没有自动过期时间;需要重新抓取时,删除该目录中对应的缓存文件或清空缓存目录。 缓存文件损坏或缓存目录不可写不会阻止正常抓取。

LLM 配置

LLMConfig 接收 API key、API base URL、模型名称和客户端类型。 客户端支持 openai_compatibleclaude,分别对应 my-llmkitOpenAICompatibleChatCompletionClaudeChatCompletion

未显式传入 llm_configllm_client 时,bodyrelevant 会自动 读取以下环境变量:

export LLM_EXTRACT_API_KEY="your-api-key"
export LLM_EXTRACT_API_BASE="https://api.openai.com/v1"
export LLM_EXTRACT_MODEL="gpt-4.1-mini"
export LLM_EXTRACT_CLIENT="openai_compatible"

四个变量需要同时配置。库本身不保存密钥,rawtext 模式也不会 读取这些环境变量。

import asyncio

from my_readurl_kit import read_url


async def main() -> None:
    body = await read_url(
        "https://example.com/article",
        output_format="body",
    )
    relevant = await read_url(
        "https://example.com/article",
        query="WebAssembly 的技术细节",
        output_format="relevant",
    )
    print(body.content)
    print(relevant.content)


asyncio.run(main())

高级调用方也可以通过 llm_client= 直接注入已构造的 my_llmkit.chat.LLMChatCompletion,此时不需要 llm_config,也不会创建 第二个模型客户端。也可显式构造 LLMConfig,或调用 LLMConfig.from_env() 读取上述变量。llm_configllm_client 不能同时传入, 且它们的优先级都高于环境变量。

LLM 通过 LLMChatCompletion.run() 以非流式方式运行。未提供配置时, body 返回 无法获取正文relevant 返回 无相关内容。模型调用失败 或返回空内容时,body 回退到规范化后的网页全文,relevant 返回 无相关内容

CLI

安装项目后可以使用 read-curl 读取网页。URL 是必需的位置参数, --output-format 支持与 Python API 相同的 rawtextbodyrelevant,默认值为 text。成功时标准输出只包含读取到的内容,便于通过 管道继续处理或重定向到文件。

read-curl "https://example.com"
read-curl "https://example.com" --output-format raw
read-curl "https://example.com" --log-level debug

--log-level 支持 debuginfowarningerrorcritical,默认为 warning。日志写入标准错误,不会混入页面内容所在的标准输出。

bodyrelevant 会在发起网页请求前从四个 LLM_EXTRACT_* 环境变量 构建并校验 LLMConfig。这些变量缺失、不完整或无效时,命令会向标准错误 输出错误并以非零状态退出。rawtext 不读取或要求这些变量。

uv run --env-file .env read-curl \
  "https://example.com/article" \
  --output-format body

uv run --env-file .env read-curl \
  "https://example.com/article" \
  --output-format relevant \
  --query "WebAssembly 的技术细节"

--query--output-format relevant 模式下用于提取相关段落;未提供或仅包含 空白时,relevant 等同于 body。其他模式会忽略它。 LLM 模式会发起外部模型请求,可能产生费用。

计划中的其他入口

入口 用途
MCP server 向支持 MCP 的客户端暴露 read-url 工具
HTTP server 向其他进程或服务提供 HTTP API

CLI、MCP 和 HTTP 层保持轻量,只负责参数转换、调用核心 API 以及输出结果。

设计边界

  • 基础抓取与 HTML 解析不依赖 LLM,应可单独使用。
  • LLM 提取建立在抓取与确定性文本解析结果之上,并通过 my-llmkit 接入模型。
  • 网络 I/O 以异步 API 为核心;如需同步 API,应由薄封装提供。
  • 公共 API 使用明确的类型标注和结构化结果,区分成功结果与请求、解析、提取错误。
  • 不在核心库中保存 API key 或其他密钥;配置由调用方显式传入或从 LLM_EXTRACT_* 环境变量读取。

当前核心包结构:

src/my_readurl_kit/
├── cli.py            # read-curl 命令行适配层
├── errors.py         # 明确的错误类型
├── extract.py        # 基于 my-llmkit 的非流式内容提取
├── fetch.py          # 基于 httpx 的 HTTP 请求与响应处理
├── models.py         # 公共结构化结果
├── parse.py          # HTML 到可读文本的确定性转换
└── reader.py         # read_url 高层 API

后续的协议入口会继续按上述边界拆分为独立模块。

开发环境

要求:

  • Python 3.10 或更高版本
  • uv

安装项目及开发依赖:

uv sync

运行静态检查:

uv run pyright

运行不包含 LLM 的真实网站集成测试(会向微信和 Orchid Files 发起外部网络请求):

uv run pytest -m "network and not llm"

测试 body 模式(启动时从 .env 注入 LLM_EXTRACT_* 变量):

uv run --env-file .env pytest -s tests/test_read_url_network.py::test_read_url_body_with_llm

测试 relevant 模式(启动时从 .env 注入 LLM_EXTRACT_* 变量):

uv run --env-file .env pytest -s tests/test_read_url_network.py::test_read_url_relevant_with_llm

两个 LLM 测试都会抓取 Orchid Files 的公开文章并发起一次非流式模型 请求。测试函数会通过 LLMConfig.from_env() 构造配置,并将它显式传给 read_url(llm_config=...)。测试会输出提取结果,也可能产生模型调用费用。未注入完整环境 变量时,测试会显式跳过,不会误用回退文本当作模型输出。

构建发行包:

uv build

当前实现可用以下方式手工检查(会发起外部网络请求):

uv run python -c 'import asyncio; from my_readurl_kit import read_url; print(asyncio.run(read_url("https://example.com")).content)'

项目默认不要求为改动新增单元测试;需要验证行为时,应在变更说明中提供简短、 可复现的手工测试步骤。只有在明确要求时才新增单元测试。

初步迁移顺序

  1. 稳定当前 Python API 和错误模型(已完成)。
  2. 在核心 API 之上增加 CLI(已完成)。
  3. 后续增加 MCP server 和 HTTP server。

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

my_readurl_kit-0.0.4.tar.gz (126.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

my_readurl_kit-0.0.4-py3-none-any.whl (16.9 kB view details)

Uploaded Python 3

File details

Details for the file my_readurl_kit-0.0.4.tar.gz.

File metadata

  • Download URL: my_readurl_kit-0.0.4.tar.gz
  • Upload date:
  • Size: 126.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.14 {"installer":{"name":"uv","version":"0.12.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for my_readurl_kit-0.0.4.tar.gz
Algorithm Hash digest
SHA256 be0b10f1a2c284bd2135cae949a854273367349dd7aed19024c908f7586454c0
MD5 165c228b75e8519d7c11a24c9b44369b
BLAKE2b-256 7330272453b57044ecab23571691f71c5750549aa5fcb5243d3273cbec6823b6

See more details on using hashes here.

File details

Details for the file my_readurl_kit-0.0.4-py3-none-any.whl.

File metadata

  • Download URL: my_readurl_kit-0.0.4-py3-none-any.whl
  • Upload date:
  • Size: 16.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.14 {"installer":{"name":"uv","version":"0.12.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for my_readurl_kit-0.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 2444a0adbf653b667e44b40d81eb46e1d097a94a33db4ab5c55ca9ce35d2da87
MD5 c41db6a19cd97b593090fc207a28e787
BLAKE2b-256 df9506fc90134ecf41c1eb76411cfe4f37aa8d3a3cc2ce605244612921c99263

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.0.4 This release

2 files

0.0.3

2 files

0.0.2

2 files

0.0.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page