Nstproxy 现已升级为 Nstdata。了解此次变化。
周一至周五 09:00 - 18:00(UTC+08:00) 公司地址
19H MAXGRAND PLAZA NO.3 TAI YAU STREET SAN PO KONG, KOWLOON HONG KONG ©2026 NST LABS TECH LTD. 保留所有权利。
Kai Watanabe Scraping Infrastructure Evangelist
在生产抓取器中重试和错误处理 TL;DR
生产抓取器需要每个 URL 的终端结果:接受、拒绝、延迟或失败及原因。仅 HTTP 200 并不算成功。
重试临时网络故障和选定状态,如 408、429 和 5xx;不要自动重试 401、403 或解析器不匹配。
尊重 Retry-After,使用带抖动的上限回退,并保持特定于来源的请求预算,以便重试不会加剧负载。
使写入操作幂等,并存储尝试计数、下一个合格时间和最后错误;处理重启不应丢失或重复接受的记录。
Nstdata Crawl 提供管理的任务状态和恢复获取,同时您的应用程序仍需验证页面含义并控制下游重试。
为什么抓取器需要超过重试循环?
重试循环解决了一类故障:请求可能稍后成功。生产抓取器还需要知道它是否到达预期页面,提取是否生成了有效记录,以及结果是否被存储。200 响应可能是同意屏幕、登录提示、空的 JavaScript 壳或备用主页。无休止地重试相同响应浪费请求,可能会超载来源。
Nstdata Crawl 可以处理浏览器渲染和获取,但应用程序仍需其自己的接受记录和重试策略。
分离四个边界:传输、HTTP 响应、内容和持久性。传输错误包括 DNS、连接和超时故障。HTTP 状态描述服务器响应,但不描述其语义内容。内容验证决定页面是否可用。持久性确认接受的记录是否持久。为每个边界指定一个独特的错误代码和所有者。Nstdata Crawl 可以简化获取边界,但不知道提取的价格是否与您的产品变体匹配。
哪些错误应该重试?
仅当故障显然是暂时的且来源允许再次请求时才重试。当前Scrapy RetryMiddleware 文档 将 408、429、500、502、503、504、522 和 524 包括在其默认重试状态中。这是一个有用的参考,而不是盲目复制的规则:特定于来源的行为和 Retry-After 重要。
症状 可能的决定 原因 连接重置或超时 有限重试 可能是暂时的;记录原因 429使用 Retry-After 延迟并减少速率 来源正在限制请求 503后退;在预算内重试 暂时不可用是合理的 401 或 403停止并检查访问 重复尝试无法获得权限 404验证 URL 或标记为缺失 通常无法通过快速重试解决 200 伴随同意/登录页面拒绝并调查 传输正常;内容错误 缺少字段 解析器或来源审查 更多相同的请求可能无法修复标记
永远不要仅仅为了强制通过被拒绝的请求而更换身份、改变头部或放弃来源限制。检查批准的访问路径或使用官方 API。HTTP 语义规范 是状态代码和头部含义的权威。
实施重试前需要什么? 定义每个来源的请求政策、最大尝试次数和经过时间预算、超时值、接受页面标记和持久化任务存储。如果使用 Python,安装一个客户端,例如 requests。记录 source_id、URL、尝试编号、最后状态/错误、next_fetch_at 和一个稳定的记录键。如果应用程序发送多个工作进程,则在它们之间协调每个主机的步伐;每个工作进程中的本地睡眠不会限制它们的综合速率。
将凭据保存在秘密管理器或环境变量中。对于管理的 Crawl 调用,从 Dashboard → Crawl Playground 获取 Nstdata API 密钥并将其作为 x-api-key 发送。内置的代理路由意味着正常的 Crawl 请求不需要单独的代理连接字段。
如何在 Python 中实现有限重试?
方法 1:重试临时 HTTP 和网络故障 第 1 步。 使用一个会话并明确设置连接和读取超时。识别客户端,仅在来源允许的访问模式中操作。
第 2 步。 单独处理可重试状态、Retry-After 和网络异常:
import email . utils
import random
import time
from datetime import datetime , timezone
import requests
RETRYABLE = { 408 , 429 , 500 , 502 , 503 , 504 }
def retry_after_seconds ( value ) :
if not value :
return None
if value . isdigit ( ) :
return max ( 0 , int ( value ) )
parsed = email . utils . parsedate_to_datetime ( value )
if parsed is None :
return None
if parsed . tzinfo is None :
parsed = parsed . replace ( tzinfo = timezone . utc )
return max ( 0 , ( parsed - datetime . now ( timezone . utc ) ) . total_seconds ( ) )
def fetch ( url , attempts = 3 ) :
with requests . Session ( ) as session :
for attempt in range ( attempts ) :
try :
response = session . get ( url , timeout = ( 5 , 20 ) )
if response . status_code not in RETRYABLE :
response . raise_for_status ( )
return response
delay = retry_after_seconds ( response . headers . get ( "Retry-After" ) )
except ( requests . Timeout , requests . ConnectionError ) :
delay = None
if attempt == attempts - 1 :
raise RuntimeError ( f"Retry budget exhausted for { url } " )
if delay is None :
delay = min ( 2 ** attempt + random . random ( ) , 30 )
time . sleep ( delay )
步骤 3. 在接受之前验证返回的页面。检查内容类型、规范来源、标题、必填字段和已知的软错误模式。如果响应为 200 但不是预期页面,记录明确的 rejected_reason。
这个例子故意有限制。在生产中,围绕重试设置最大经过时间,并通过推迟任务而不是让一个 worker 处于睡眠状态来验证任何非常大的 Retry-After 是否超出工作预算。代码不会重试 401 或 403;raise_for_status() 会将它们抛出以供策略审查。
如何确保 worker 重启后重试安全?
方法 2:使用持久化任务状态机 步骤 1. 将 URL 任务存储在队列或表中,具有唯一键和状态,例如 pending、leased、retry_pending、accepted、rejected 和 failed_terminal。
步骤 2. 给 worker 一个有时间限制的租约。在确认任务之前先写入原始工件和验证结果。如果 worker 在写入后但在确认之前崩溃,下一个 worker 必须识别相同记录的版本并避免重复插入。
步骤 3. 在可重试的失败时,保存尝试次数和 next_fetch_at。在政策拒绝或内容拒绝时,记录终止原因并停止自动请求。在每次运行结束时协调提交和终止计数。
内容哈希对于变更检测很有用,但不应是唯一身份。两个不同的 URL 可能合法共享文本,并且一个 URL 可能产生多个版本。使用源 ID 和规范 URL 来形成实体身份,加上哈希和抓取时间作为版本。
如何诊断无声的抓取失败?
方法 3:添加语义接受检查 步骤 1. 保存一个小的固定集合:正常页面、重定向、缺失字段、已知同意页面、错误页面和 JavaScript 外壳。
步骤 2. 为每种页面类型定义必需的标记。产品记录可能需要产品 ID、货币和可见价格;文章需要标题和正文。在检索后和存储前验证这些标记。
步骤 3. 在源或解析器更改后对已接受和已拒绝的记录进行抽样。根据域警报接受收益和拒绝原因,而不仅仅是请求错误率。
Nstdata 如何帮助保持获取错误可观察? Nstdata Crawl 是一个用于 LLM 就绪数据的网络爬虫 API,接受经过审查的页面或有界网站工作,并暴露任务状态和结果。其文档区分了外部 HTTP 响应与嵌套任务的 success、status 和错误代码;应用程序必须检查两者。内置的重试和代理编排可以减少基础设施工作,但任务仍然可能失败,返回被拒绝的页面,或产生不符合您模式的内容。
LLM 就绪输出: Markdown 和清理后的 HTML 让下游 RAG 或提取代码专注于相关内容;原始数据有助于诊断错误转换。链接、截图和 PDF 提供导航和视觉证据。只选择消费者所需的格式,并在大输出被单独存储时检查 markdownRef、htmlRef 或其他引用。
内置代理路由: 标准 API 请求采用 x-api-key 和页面选项,无需单独的 Host、Port、Username、Password 或 Protocol 代理字段。这减少了允许收集的设置和凭证处理。代理路由不授权访问被源拒绝的内容。
任务可见性: 网站工作通过文档状态路由报告完成、失败和待处理的计数。您的应用程序仍然应协调接受和拒绝的业务记录。
如何将 Nstdata Crawl 添加到重试工作流中? 步骤 1. 在 仪表板 → 爬虫游乐场 中获取 API 密钥并选择一个审核的测试 URL。根据当前文档限制设置请求超时。
步骤 2. 提交单个页面并保存原始响应以进行诊断比较:
curl --request POST 'https://api.nstdata.io/api/v1/crawl/scrape/submit-sync' \
--header "x-api-key: ${NSTDATA_API_TOKEN} " \
--header 'Content-Type: application/json' \
--data '{"url":"https://example.com/","formats":["markdown","html"],"timeout":60000}'
第 3 步。 检查外部 HTTP 状态,然后检查 data.success、data.status、任何任务代码以及 data.data.metadata.statusCode。在需要时通过 GET /api/v1/crawl/storage/read?st={ref} 获取参考令牌。应用您的语义接受规则并存储终端结果。该代码片段遵循官方文档,但在没有账户密钥的情况下无法进行实时执行。
在生产环境中,在提供者和应用层都限制重试次数,以防止同一失败页面反复消耗预算。对于页面转换之外的允许浏览器交互,Nstdata Cloud Browser 是一款独立产品。下一步是故障演练:使一页超时、一页返回软错误、一页通过,然后确认每个任务的结束状态正确。
抓取器何时应打开断路器? 当重复失败表明更多请求不太可能有帮助时,暂停来源。403 响应、挑战页面、空渲染或解析器拒绝的突然增加应打开特定来源的电路并警告所有者。仅在审查过访问或来源问题后使用短小且受控的探测。断路器保护目标免受不必要的负载,并防止不良模板污染数据集。记录打开时间、原因以及谁授权恢复。
常见问题 不必。对于预算内的临时故障进行重试;停止并审查授权、永久缺失页面和解析器缺陷。
问:我应该忽略长时间的 Retry-After 值吗?
不应该。当请求的等待时间超过您的工作预算时,请推迟任务或停止任务;不要缩短来源的等待时间以适应本地循环。
不。它处理获取恢复和任务状态,而您的应用必须处理队列交付、验证、索引和终端故障。
Lena Zhou
Oct. 30th 2026
支持 JavaScript 渲染,成功率达 99.8%
将任意网站转换为 Markdown、HTML、JSON、链接、PDF 等格式,无需管理爬取基础设施。 开始免费爬取 →