mcpField
B
bulk-url-checker

bulk-url-checker

远程服务
github.com/carlosofscience开发工具02 周前更新
代码仓库

关于 bulk-url-checker

bulk-url-checker 是用于提交大批量网址检查任务的 Python 客户端和命令行工具,可返回状态码、重定向及失效链接结果,并支持轮询任务和安全重试。

主要功能

  1. 01批量检查网址并返回状态码
  2. 02获取重定向链和失效链接结果
  3. 03提交、轮询并分页读取任务
  4. 04幂等重试与签名 Webhook
  5. 05命令行导出 CSV、JSON 和 JSONL

适用场景

  1. 01检查大量网址中的失效链接
  2. 02恢复或跟踪长时间运行的检查
  3. 03将网址检查结果导出为报告

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址https://mcp.bulkurlchecker.com/mcp
一键复制安装命令
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。

工具

5
参数类型必填说明
urlsarray是要检查的 URL。每个 URL 都必须包含 http:// 或 https:// 协议。

详细介绍

bulkurlchecker

PyPI version Python versions License: MIT

用于调用 Bulk URL Checker API 的 Python 客户端。

省去代理轮换、速率限制器、软 404 检测器和重试分类器——这些功能原本需要你花两周时间来构建。 提交数千个 URL,即可获取状态码、重定向链和失效链接检测结果,数据以纯 Python 对象的形式返回。由托管云服务提供支持,具备住宅代理和按域名限流功能。

安装

pip install bulkurlchecker

5 行示例

from bulkurlchecker import Client

client = Client(api_key="uck_live_...")
results = client.check_urls(["https://example.com", "https://example.org"])
for r in results.results:
    print(r.url, r.status_code, "BROKEN" if r.is_broken else "ok")

请前往 https://app.bulkurlchecker.com/dashboard/api-keys 获取 API 密钥。前 300 个 URL 免费,无需绑定银行卡。

返回结果

results = client.check_urls(urls)

results.status            # 'completed' | 'paused' | 'failed' | 'cancelled'
results.timed_out         # True if the wait deadline passed (job still running)
results.total_urls        # how many URLs the engine accepted
results.completed_urls    # how many it finished checking
results.duplicates_removed
results.invalid_urls_rejected

for r in results.results:
    r.url                # the original URL you submitted
    r.final_url          # after redirects
    r.status_code        # 200, 301, 404, 429, 500, ...
    r.redirect_chain     # list of intermediate URLs
    r.is_broken          # True if the engine flagged this as broken
    r.is_soft_404        # True if 200 OK but page content says "not found"
    r.response_time_ms

# Convenience properties:
results.broken           # list of URLResult where is_broken == True
results.soft_404s        # list where is_soft_404 == True

命令行用法

安装 [cli] 附加组件即可使用 bulkurlchecker 命令:

pip install 'bulkurlchecker[cli]'
export BULKURLCHECKER_API_KEY=uck_live_...

# One URL per line in urls.txt → CSV on stdout
bulkurlchecker check urls.txt > report.csv

# Pipe from anywhere
sitemap-extractor mydomain.com | bulkurlchecker check - --output jsonl > report.jsonl

# Only show broken URLs, ad-hoc input
bulkurlchecker check --urls "https://example.com,https://example.org" --only-broken

# Two-step (submit, then poll & fetch later)
JOB=$(bulkurlchecker submit urls.txt)
bulkurlchecker status "$JOB"
bulkurlchecker results "$JOB" --output csv > report.csv

输出格式:csv(默认)、json、jsonl。运行 bulkurlchecker check --help 查看完整的标志列表。

处理较大的任务:提交并轮询

check_urls() 会在服务端阻塞最多 15 分钟。对于等待时间可能超时的列表,请使用以下两步模式:

job = client.submit(my_500k_urls)
print(f"Submitted {job.job_id}, {job.total_urls} URLs queued")

# Poll explicitly, or use the convenience method
done = client.wait_until_done(job.job_id, timeout=3600)

# Stream results in pages
for batch in client.iter_results(job.job_id, page_size=1000):
    for r in batch:
        if r.is_broken:
            print(r.url, r.status_code)

使用 idempotency_key 安全重试

在 submit() 或 check_urls() 中传入幂等键,即可在网络故障时安全重试。服务器会将响应缓存 24 小时;使用相同的键和相同的请求正文重试时,会返回原始结果,而不会创建重复任务。

import uuid

key = str(uuid.uuid4())  # generate once per logical request

# First call: creates a new job.
job = client.submit(urls, idempotency_key=key)

# Network blip, no clean response received? Just retry with the same
# key -- you'll get the SAME job summary back, no duplicate submission.
same_job = client.submit(urls, idempotency_key=key)
# job.job_id == same_job.job_id

相同的 idempotency_key 配上不同的 urls 会返回 409 Conflict(以 ValidationError 的形式抛出),这样客户端重复使用密钥提交新载荷时会明确报错,而不会悄悄映射到错误的缓存结果。

接收 Webhook

任务完成时,我们会向你注册的端点发送包含签名载荷的 POST 请求。请先验证签名,再信任请求正文——否则,任何知道你端点 URL 的人都可以发送伪造事件。

from flask import Flask, request
from bulkurlchecker import verify_signature, InvalidSignatureError

SECRET = os.environ["MY_WEBHOOK_SECRET"]  # the signing_secret we showed once

app = Flask(__name__)

@app.route("/webhook/bulkurlchecker", methods=["POST"])
def webhook():
    try:
        verify_signature(
            request.get_data(),  # RAW bytes — not request.get_json()
            request.headers.get("Bulkurlchecker-Signature", ""),
            SECRET,
        )
    except InvalidSignatureError:
        return "", 401
    event = request.get_json()
    if event["type"] == "job.completed":
        job_id = event["data"]["job_id"]
        # ... fetch results, update your DB, ping Slack, etc ...
    return "", 200

请前往 https://app.bulkurlchecker.com/dashboard/webhooks 注册端点并获取密钥(也可通过 POST /api/v2/webhooks/endpoints 操作)。

verify_signature() 默认会强制执行 5 分钟的时间戳容差,以防止重放攻击。可通过 tolerance_seconds= 调整。

错误处理

所有错误都继承自 BulkURLCheckerError。若要针对不同失败情况采取不同处理方式,请捕获具体的子类:

from bulkurlchecker import (
    Client,
    BulkURLCheckerError,
    AuthenticationError,
    RateLimitError,
    QuotaError,
    ValidationError,
)

try:
    results = client.check_urls(urls)
except QuotaError as e:
    print(f"Out of credits. Top up at https://app.bulkurlchecker.com/billing")
except RateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after}s.")
except AuthenticationError:
    print("API key rejected — check it's not revoked.")
except ValidationError as e:
    print(f"Bad request: {e}")  # bad URLs, too many URLs, etc.
except BulkURLCheckerError as e:
    print(f"Other error: {e} (request_id={e.request_id})")

每个错误都包含 status_code、code(服务器提供的机器可读字符串)、request_id(用于联系支持团队)以及 details(服务器提供时)。

为什么要用这个,而不是用 httpx + asyncio 自己编写检测器?

坦白说:对于 ≤500 个 URL,你不需要它。标准的 requests/httpx 工具链足以应付。

规模增大后,就会遇到瓶颈:

问题自己搭建本 SDK
并发asyncio + 精心配置的信号量已处理
跨住宅 IP 轮换代理每月 90 美元以上的 Webshare / Bright Data 订阅 + 自定义代码已处理
按域名限流(避免向单个主机发送过多请求)自己接入已处理
区分真正的 403 和“你被拦截了”的 403靠猜测和测试已处理
检测软 404(200 OK +“未找到”正文)为每种模板编写正则表达式 / 启发式规则已处理
重试分类(临时错误还是永久错误)花数周调优已处理
长时间运行任务的状态(崩溃后恢复)Redis + 队列 + Worker 基础设施已处理
工程师投入,第 1–4 周$$$无,今天即可上线

如果你已经因为 httpx + 代理轮换搭建忙了一个周末,你就知道我们在说什么。

定价

  • **首月免费:**Starter 计划提供 15,000 次 URL 检查,无需信用卡。 首次通过 API 或 SDK 集成成功运行后,试用期将延长 为一个月的 Pro 计划:50,000 次 URL 检查,每个账户限一次。
  • **之后:**每个账户每月均包含 300 次 URL 检查。
  • Starter:$9/月或 $90/年,每月 15,000 个 URL
  • Pro:$29/月或 $290/年,每月 50,000 个 URL
  • Agency:$99/月或 $990/年,每月 200,000 个 URL

所有计划均包含定期检查,以及电子邮件、Slack 和 webhook 告警。一次性额度包售价从 $5(3,000 次检查)起,额度可结转。当前价格:https://bulkurlchecker.com/#pricing

链接

稳定性

SDK 遵循语义化版本规范。在我们处于 0.x 阶段时,次要版本可能包含破坏性变更(我们会始终在 CHANGELOG.md 中注明)。达到 1.0 后,你可以放心固定主版本。

许可证

MIT。请参阅 LICENSE。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。