ArchiveBox 实时进度监控 API 深入解析:progressmonitor 模块与 progress.json 端点的完整实现 📅 发布时间:2026/9/20 7:35:31 👁 浏览次数: 后端数据工程【免费下载链接】ArchiveBox Open source self-hosted web archiving. Takes URLs/browser history/bookmarks/Pocket/Pinboard/etc., saves HTML, JS, PDFs, media, and more...项目地址https://gitcode.com/gh_mirrors/ar/ArchiveBox点击查看免费下载本篇指南围绕 ArchiveBox 的archivebox.progressmonitor.views模块展开深入剖析其向 Django Admin 管理界面提供实时进度监控能力的三个核心函数progress_endpoint、_live_progress_plugin_names与live_progress_view。你将理解progress.json端点如何聚合 Crawl爬取任务、Snapshot快照与 ArchiveResult归档结果三级状态、如何做权限隔离与作用域过滤、如何探测 orchestrator/worker 进程以及前端进度监控面板如何轮询消费这些数据。读完即可在部署环境中直接调试、二次开发该端点并为自己的 ArchiveBox 集成提供监控数据源。1. 模块定位progressmonitor 应用是做什么的progressmonitor是 ArchiveBox 的一个独立 Django 应用AppConfig 定义于 archivebox/progressmonitor/apps.pyname archivebox.progressmonitor职责非常聚焦为 Admin 后台提供非阻塞的实时进度数据。它对外只暴露一个 HTTP 端点GET /progress.json对内通过缓存、线程与数据库查询的精心设计保证即使归档集合非常庞大监控轮询也不会拖垮爬取主流程。本模块对应的 API 参考文档位于 docs/apidocs/archivebox/archivebox.progressmonitor.views.md由 Sphinxautodoc2从源码 docstring 自动生成其 Module Contents 列出了模块的三个公开函数。下文将以这三个函数为骨架逐一结合源码展开。从模块源码结构看progressmonitor由以下文件组成文件职责archivebox/progressmonitor/views.py三个公开函数与progress.json端点的全部业务逻辑archivebox/progressmonitor/collection.py非阻塞、纯数据库的集合总量统计collection_summaryarchivebox/progressmonitor/templates/progressmonitor/progress_monitor.htmlAdmin 页面内嵌的进度监控前端组件约 1900 行含样式与轮询 JSarchivebox/progressmonitor/apps.pyDjango App 配置2.progress_endpoint同源进度端点的规范 URL 生成器def progress_endpoint(scope: Literal[crawl, snapshot] | None None, object_id: object | None None) - str: Return the canonical same-origin progress endpoint for monitor embeds. if not scope or object_id is None: return /progress.json return f/progress.json?{scope}_id{str(object_id).replace(-, )}这是模块中最轻量的一个函数源码见 archivebox/progressmonitor/views.py作用是为监控面板嵌入点生成规范的、同源same-origin的进度端点 URL全局模式当scope为空或object_id为None时返回裸路径/progress.json即无过滤的全局监控作用域模式返回带查询参数的 URL如/progress.json?snapshot_id...或/progress.json?crawl_id...把监控面板聚焦到单个快照或单个爬取任务ID 规范化str(object_id).replace(-, )会把带连字符的 UUID 转成 Compact UUID去掉所有-。这与进度端点内部对 ID 的处理保持一致——Process.pwd指向Snapshot.output_dir目录名使用 Compact UUID 十六进制片段因此进度数据里统一使用无连字符的紧凑 ID 以方便进程行与快照/爬取行互相匹配源码注释见 archivebox/progressmonitor/views.py。实际调用方progress_endpoint被三处 Admin 层代码调用用于把进度面板注入不同管理页面快照变更页archivebox/core/admin_snapshots.py 中当快照状态为queued/started/paused时设置context[progress_auto_expand] True并注入progress_endpoint(snapshot, obj.id)即页面自动展开进度面板并聚焦该快照爬取任务变更页archivebox/crawls/admin.py 对状态为queued/started/paused的 Crawl 注入progress_endpoint(crawl, crawl.id)快照模型自身archivebox/core/models.py 的Snapshot.as_json()系列方法中为每个快照附带progress_endpoint(snapshot, self.id)与progress_auto_expand标志供 API 序列化与模板共用。模板端通过data-progress-endpoint属性接收该 URL见 archivebox/progressmonitor/templates/progressmonitor/progress_monitor.htmlJS 侧读取后作为轮询地址div idprogress-monitor ...>const progressEndpoint monitor.dataset.progressEndpoint || /progress.json; function fetchProgress() { fetch(progressEndpoint, { credentials: same-origin }) .then(response { if (!response.ok) throw new Error(HTTP ${response.status}); return response.json(); }) .then(data { ... updateProgress(data); }) .catch(error { ... }); }3._live_progress_plugin_names区分下载类与索引类插件lru_cache(maxsize1) def _live_progress_plugin_names() - tuple[frozenset[str], frozenset[str]]: plugin_configs discover_plugin_configs() indexing_plugin_names frozenset( plugin_name for plugin_name, plugin_config in plugin_configs.items() if {search, flush}.issubset(plugin_config.get(commands, {})) ) download_plugin_names frozenset( plugin_name for plugin_name, plugin_config in plugin_configs.items() if plugin_config.get(output_mimetypes) and plugin_name not in indexing_plugin_names ) return download_plugin_names, indexing_plugin_names源码位于 archivebox/progressmonitor/views.py。该函数把已发现的插件分成两类供进度端点把下载中与索引中的工作量分开统计索引类插件indexingconfig.json的commands中同时声明了search与flush命令的插件如全文搜索后端。这类插件不产出存档文件而是建立索引下载类插件download声明了output_mimetypes即会产出特定 MIME 类型的输出文件且不属于索引类的插件如singlefile、wget、chrome、screenshot等。它依赖的discover_plugin_configs()定义于 archivebox/plugins/discovery.py负责汇总所有插件的config.jsonJSONSchema 元数据。整个函数用lru_cache(maxsize1)缓存——因为插件清单是包级元数据而非运行时用户配置缓存后每次轮询无需重新扫描插件目录。在live_progress_view中返回的二元组被解包后用于构造两类独立统计详见第 5 节。4.live_progress_viewprogress.json端点的核心实现def live_progress_view(request): Simple JSON endpoint for live progress status - used by admin progress monitor.这是模块主体源码约 300 行archivebox/progressmonitor/views.py。路由注册于 archivebox/core/urls.pypath(progress.json, live_progress_view, namelive_progress)视图名live_progress也是测试中reverse(live_progress)的依据。其处理流程可以拆成六个阶段。4.1 权限控制与作用域解析端点支持三种调用方式权限要求各不相同snapshot_id_filter (request.GET.get(snapshot_id) or ).strip().replace(-, ) crawl_id_filter (request.GET.get(crawl_id) or ).strip().replace(-, ) is_admin is_admin_user(request)?snapshot_id...快照作用域校验 UUID 格式非法返回400 {error: Invalid snapshot_id}随后加载快照并调用can_view_snapshot(request, scoped_snapshot)做快照级 ACL 校验权限工具位于 archivebox/core/permissions.py无权限返回403。这是唯一允许非管理员访问的作用域?crawl_id...爬取作用域强制要求 staff 身份。源码注释说明原因爬取任务没有单独的 per-crawl ACL 辅助函数且一个 crawl 内部可能混合多种快照权限级别所以直接要求管理员无参数全局作用域同样强制要求管理员身份防止任何匿名访客窥探归档进度与内部路径。另外当管理员是 staff 而非 superuser 时所有数据自动按该用户创建过滤crawl_scope过滤created_byrequest.usersnapshot_scope过滤crawl__created_byrequest.userarchiveresult_scope同理级联过滤。4.2 当前运行窗口过滤为避免把上一次运行遗留的旧结果误报为当前进度视图定义了时间窗口判断def is_current_run_timestamp(event_ts, run_started_at) - bool: if run_started_at is None: return True if event_ts is None: return False return event_ts run_started_at def archiveresult_matches_current_run(ar, run_started_at) - bool: if run_started_at is None: return True if ar.status in (QUEUED, STARTED, BACKOFF): return True event_ts ar.end_ts or ar.start_ts or ar.modified_at or ar.created_at return is_current_run_timestamp(event_ts, run_started_at)尚未开始QUEUED/STARTED/BACKOFF的结果视为当前运行的一部分已结束的结果必须满足end_ts/start_ts/modified_at/created_at run_started_at快照的downloaded_at或created_at才计入。对应测试test_live_progress_excludes_old_archiveresults_from_previous_snapshot_run见 archivebox/tests/test_ui_live_progress.py把旧结果的start_ts/end_ts拨回一小时前断言all_plugins只保留当前运行的插件项。4.3 orchestrator / worker 进程探测端点需要回答后台编排进程是否还活着、跑在哪个 PID优先查数据库Machine.current().id上是否存在process_typeORCHESTRATOR且statusRUNNING的 Process模型位于 archivebox/machine/models.py若没有退而通过 archivebox/workers/supervisord_util.py 的get_existing_supervisord_processget_worker(supervisor, worker_runner)查询 supervisord 管理的worker_runner进程状态为STARTING/RUNNING视为运行中任一命中即orchestrator_running Trueorchestrator_pid取对应 PID。这一状态驱动了worker_state的最终判定如果快照/爬取处于 STARTED 却没有匹配到运行中的 worker PID且超过 30 秒无更新视图会把状态标为crashed否则为waiting。对应测试test_live_progress_reports_real_orchestrator_process_runningarchivebox/tests/test_ui_live_progress.py真实拉起archivebox manage shell进程并写入 Process 表断言端点返回正确的orchestrator_pid。4.4 全局统计计数视图对三类模型按状态批量聚合生成顶层统计字段字段含义数据来源crawls_active/crawls_queued运行中 / 排队中的爬取任务Crawl.status_counts(scope, (QUEUED, STARTED, PAUSED))snapshots_active/snapshots_queued运行中 / 排队中的快照Snapshot.status_counts(scope, Snapshot.OPEN_STATES)archiveresults_active/archiveresults_queued全部运行中 / 排队中的归档结果ArchiveResult.status_counts(scope, (QUEUED, STARTED))downloads_active/downloads_queued下载类插件的运行中 / 排队数对download_plugin_names过滤后统计indexing_active/indexing_queued索引类插件的运行中 / 排队数对indexing_plugin_names过滤后统计crawls_recent最近 24 小时内创建的爬取任务数created_at__gtenow - timedelta(days1)计数注意下载类统计还额外要求快照与爬取都处于可运行状态Snapshot.RUNNABLE_STATES/Crawl.RUNNABLE_STATES避免把已结束任务的排队结果算进去。4.5 层级化的 active_crawls 数据树这是响应体中最复杂的部分构建一棵crawl → snapshot → archive result/process的三级树并施加明确的截断上限防止大集合拖垮端点max_active_crawls 10 max_queued_crawls 10 max_started_snapshots_per_crawl 50 max_queued_snapshots_per_crawl 50Crawl 层STARTED的取最近修改的 10 个PAUSED的额外满足三个条件之一才展示——12 小时内暂停过、存在到期待运行的快照retry_at now、存在 QUEUED 的归档结果QUEUED的取最近 10 个。被截断的排队爬取数记录在queued_crawls_hiddenSnapshot 层每个 crawl 内STARTED快照按-modified_at取 50 个QUEUED按modified_at升序取 50 个溢出数量记入queued_snapshots_hidden字段名queued_snapshots_hidden。纯排队且无 worker 的快照以紧凑数组[id, url, title?]呈现避免展开大量字段ArchiveResult / Process 层只有detailed_snapshot_ids非 QUEUED 快照会预取归档结果select_related(process)见 archivebox/progressmonitor/views.py。源码注释特别强调大型爬取可能有数千个已封存快照如果全部预取其结果会让进度端点与 runner 竞争数据库资源因此只对页面上实际展示的活动快照拉取结果。每个快照还会计算插件进度百分比SUCCEEDED/FAILED/SKIPPED/NORESULTS记为 100STARTED的按已运行时间与进程超时的比例min(99, max(1, elapsed/timeout*100))计算否则为 0。快照总进度为各插件进度均值插件展示信息hook_details()把on_Snapshot__93_hashes.py这类 hook 文件名解析为(plugin, label, phase, hook_name)四元组——phase按命名推断为install/crawl/snapshotlabel去掉数字序号与下划线如93_hashes→hashes输出链接archiveresult_output_path()依据output_files映射含root_relative标记与output_str推断产物相对路径snapshot_view_url()再拼接出归档视图 URL通过 archivebox/core/routes_util.py 的build_web_url从而提供favicon_url、preview_url截图、screencast_url最新帧等字段worker 状态snapshot_process_pids在遍历运行进程时建立通过把Process.pwd的路径片段与快照 Compact UUID 反匹配见find_snapshot_for_process命中即worker_pid字段worker_state为running否则waiting若编排进程也不存在则crashed。每个 crawl 还会附带setup_plugins来自on_CrawlSetup__*的 Process 行、crawl_progress已封存快照数/总数、crawl_output_size与avg_snapshot_sizeprintable_filesize格式化工具位于 archivebox/misc/logging_util.py、配置限额max_urls/max_crawl_size/crawl_timeout/max_snapshot_size来自get_config(crawl...)解析的CRAWL_MAX_URLS、CRAWL_MAX_SIZE、CRAWL_TIMEOUT、SNAPSHOT_MAX_SIZE、以及seconds_until_retry、retry_at_future等排期状态方便运维诊断为什么爬取还没开始。4.6 响应序列化与错误降级正常响应优先使用ujson序列化更快不可用时回退到 Django 的JsonResponse。顶层字段还包括is_admin、scope、orchestrator_running、orchestrator_pid、total_workers、server_time。当请求带?collection1且为全局管理员作用域时额外附加collection字段——即 archivebox/progressmonitor/collection.py 的collection_summary(request.user)def collection_summary(user): user_id None if user.is_superuser else user.pk key fprogress-collection:{all if user_id is None else user_id} summary cache.get(key) ... def refresh(): totals snapshots.aggregate(snapshotsCount(*), bytesSum(output_size)) ... cache.set(key, totals, timeout3600) Thread(targetrefresh, namecollection-summary, daemonTrue).start()该函数输出{snapshots, bytes, sampled_at}。设计要点绝不让 HTTP 请求等待大表扫描——即使SUM(output_size)走覆盖索引也要避免多个客户端同时触发。它用进程内Lock加 Django cache 的add(key, timeout60)双重防抖过期后仅由第一个请求在后台线程刷新其余请求继续返回旧缓存缓存 1 小时失败也被限流避免数据库锁死时每个侧边栏轮询都产生错误日志。SQLite 下COUNT(*) SUM(output_size)依赖core_snapshot的覆盖索引COVERING INDEX测试用EXPLAIN QUERY PLAN断言了这一点archivebox/tests/test_ui_live_progress.py。测试同时验证非 superuser 的 staff 只能看到自己名下的总量test_collection_summary_is_scoped_to_staff_owner以及 20 次轮询中缓存命中后不重复执行聚合查询。错误降级整个视图包在try/except (DatabaseError, OSError, RuntimeError, TypeError, ValueError)中任何异常都返回500且带全套零值字段orchestrator_running: False、active_crawls: []等保证前端拿到可解析的稳定结构只有settings.DEBUGTrue时才附上traceback对应测试test_live_progress_error_response_hides_traceback_without_debug。5. 路由接线普通路径与子域名托管路径progress.json除了主路由 archivebox/core/urls.py 外还有一个特殊转发路径当 ArchiveBox 启用子域名托管subdomain routing时快照访问请求会被SnapshotHostView接管archivebox/core/views.py其中rel_path progress.json的情况会直接转发到同一个live_progress_view。源码注释说明了设计意图Host routing forwards every snap-* path to SnapshotHostView, so we forward /progress.json on through to the same view used everywhere else. The caller passes snapshot_id explicitly in the query string — we dont read it from the subdomain (this keeps the endpoint identical across all security modes).即端点行为在任意安全模式下完全一致作用域只通过查询参数传递不依赖子域名。这也正是progress_endpoint(snapshot, obj.id)生成的?snapshot_id参数能在快照详情页正常工作的原因——页面与端点同源。另外 archivebox/misc/monkey_patches.py 还针对该端点做了日志降噪GET /progress.json耗时低于 1 秒的请求不进入慢请求日志因为它是高频轮询接口。6. 前端消费方式与轮询节奏前端组件位于 archivebox/progressmonitor/templates/progressmonitor/progress_monitor.html整体是一个深色主题GitHub 风格配色的可折叠监控面板包含 orchestrator 状态指示灯、统计徽章、爬取树等区块。关键交互逻辑轮询页面加载即startPolling()之后按pollDelayMs间隔setInterval(fetchProgress, pollDelayMs)拉取progress.json标签页隐藏时stopPolling()暂停重新可见时恢复避免后台标签页浪费带宽错误呈现HTTP 非 2xx、JSON 含error字段、网络异常都会把状态灯置为errorBackend not responding并在顶部显示错误信息操作联动面板内嵌的取消按钮通过 PATCH 调用/api/v1/crawls/crawl/{id}或/api/v1/core/snapshot/{id}action: cancel成功后立即刷新进度数据guest 模式当data.is_admin false即快照作用域下的普通访客时面板切换为只读 guest 样式。7. 测试验证矩阵该端点的行为被 archivebox/tests/test_ui_live_progress.py 系统覆盖可以作为理解语义的权威参考也便于你在修改后回归验证测试验证点test_live_progress_rejects_unauthenticated_unscoped_request匿名全局访问返回 403 且响应不泄露任何内部字段test_admin_live_progress_path_does_not_bypass_admin_auth/admin/live-progress/不绕过 Admin 鉴权test_live_progress_scope_accepts_compact_and_dashed_snapshot_ids/..._crawl_ids带连字符与紧凑 UUID 均可作为作用域参数响应中统一为紧凑 IDtest_live_progress_excludes_old_archiveresults_from_previous_snapshot_run上一轮运行遗留结果被时间窗口过滤test_live_progress_does_not_hide_active_snapshot_results_when_modified_at_moves活动中的 wget 结果即使modified_at变化也不会被误过滤test_live_progress_hides_finished_cancelled_crawlSEALED 的爬取不出现在active_crawls但全局排队计数仍准确test_live_progress_shows_old_paused_crawl_with_due_snapshot_work暂停但有待处理快照的爬取以紧凑数组形式展示test_live_progress_routes_crawl_process_rows_to_crawl_setupon_CrawlSetup__89_chrome_kill_zombies.js进程行进入setup_pluginslabel 解析为chrome kill zombiestest_live_progress_uses_snapshot_process_rows_before_archiveresults/..._merges_process_rows...进程行与归档结果行按去重键合并source分别标记为process与archiveresulttest_live_progress_ignores_unscoped_running_processes_when_no_crawls无归属快照/爬取的进程不计入total_workerstest_live_progress_does_not_clean_stale_running_processes进度端点只读不会清理或篡改脏的 RUNNING 进程记录test_live_progress_reports_real_orchestrator_process_running真实进程写入 Process 表后端点上报正确orchestrator_pidtest_collection_summary_reports_stored_sizes/..._is_scoped_to_staff_owner?collection1的总量与权限隔离缓存命中后不再执行聚合 SQL8. 小结如何调试与二次开发该端点结合以上分析在日常运维与二次开发中你可以这样使用progress.json快速体检后台状态浏览器或curl访问/progress.json需管理员会话观察orchestrator_running、total_workers、crawls_active、snapshots_queued等顶层字段即可判断爬取管线是否健康单对象聚焦在快照/爬取详情页按 F12 查看#progress-monitor的data-progress-endpoint属性或直接请求/progress.json?snapshot_idid、/progress.json?crawl_ididcrawl 作用域需 staff排查单个任务卡住的原因——worker_state为crashed表示编排进程失联retry_at_future/seconds_until_retry表示任务在退避等待can_start/urls_preview用于诊断爬取为何无法启动容量与性能注意端点自带的截断上限10 个活动爬取、每爬取 50 个快照与collection_summary的后台线程刷新机制这些是监控不拖垮归档的关键设计二次开发时不要轻易移除权限模型记住三个作用域全局/crawl 需管理员snapshot 走快照 ACLstaff 非 superuser 只能看到自己创建的任务数据修改后的回归运行pytest archivebox/tests/test_ui_live_progress.py验证端点语义未被破坏。archivebox.progressmonitor.views虽然只有三个公开函数却完整承载了 ArchiveBox 的实时进度中枢职责它把 Crawl / Snapshot / ArchiveResult / Process 四种模型、插件元数据、子域名路由与 Admin 前端串联成一个低开销、高可用的 JSON 数据源。理解这一模块就理解了 ArchiveBox 后台监控面板背后的全部机制。赞分享后端数据工程【免费下载链接】ArchiveBox Open source self-hosted web archiving. Takes URLs/browser history/bookmarks/Pocket/Pinboard/etc., saves HTML, JS, PDFs, media, and more...项目地址https://gitcode.com/gh_mirrors/ar/ArchiveBox点击查看免费下载相关推荐ArchiveBox Crawl REST API 深度解析/api/v1/crawls 端点、请求模式与实现细节ArchiveBox Crawl REST API 深度解析/api/v1/crawls 端点、请求模式与实现细节 ArchiveBox 的 archiveb后端数据工程ArchiveBox REST API 的 CLI 子命令端点archivebox.api.v1_cli 模块全解析ArchiveBox REST API 的 CLI 子命令端点archivebox.api.v1_cli 模块全解析 ArchiveBox 在 Web 服务进后端数据工程CANN/GE操作符重载C样例指南样例使用指导 1、功能描述 本样例使用操作符重载进行构图旨在帮助构图开发者快速理解操作符重载的定义 2、目录结构 angular2html cpp/ ├──后端数据工程上一篇Veloren游戏UI系统终极指南如何快速掌握egui框架与用户界面设计下一篇多语言AI代理终极指南Browser-Use WebUI国际化界面详解创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考