直接答案:第 83 期缓存的 36 个文章页里,188 张站外图片只来自 2 个主机;其中 H1 承载 6 个站点的 149 张图。2026-11-06 18:42–18:44,对 H1 的 6 条图片 URL 各发 6 种请求(裸请求、Chrome UA、加 Accept、加 Referer、加 Sec-Fetch、HEAD),36 次全部返回 HTTP 567、0 字节;对照主机 C1 的 6 次请求全部返回 200 与 image/png。改变请求头没有解锁 H1。
2026-11-07 00:40–00:42 做了约 6 小时后的跨日复检:状态分层不变,细节见下文“跨日复检”。
浏览器对照也没有复现“浏览器能显示”:直接打开同一图片地址得到 HTML 403 挑战页;打开来源文章页,Logo 和正文配图都显示为占位图。这个结论只属于本机、本网络出口、本时间窗。
方法:先发现,再固定变量
复用第 83 期的 36 个文章页缓存(10 站,2026-11-03 抓取),只解析静态 <img src>,排除 data:/blob:/javascript: 与仅 data-src 的懒加载。先按主机汇总站外图片,再对每个主机取文档顺序第一条 URL 发一次裸请求(Python urllib 默认 UA),得到 567 与 200 两类主机。
实验组为 H1 上 6 个受影响站点各 1 条 URL;对照组为 C1 上 1 条 URL。每条 URL 跑 6 种请求,同主机相邻请求间隔 1.2 秒,超时 20 秒,共 42 次请求。只记录实际状态、Content-Type、Content-Length、读取字节数与 Server 头,不推断 CDN 策略。
| 项 | 判定 | 边界 |
|---|---|---|
| 图片 | img 带非空、非 data: 的 src | CSS 背景图不计 |
| 站外 | 注册域与文章页不同 | 子域算站内 |
| H1 / C1 | 裸请求返回 567 / 200 的站外主机 | 只代表本机本次请求 |
| 可用 | 200 且 Content-Type 为 image/* 且读到字节 | 不判断版权与长期可用 |
结果:6 种请求头,36 次全是 567
| 变体 | 请求头 / 方法 | H1(6 条 URL) | C1(1 条 URL) |
|---|---|---|---|
| V0 | 裸请求(urllib 默认 UA) | 6 × 567 | 1 × 200 |
| V1 | Chrome UA | 6 × 567 | 1 × 200 |
| V2 | + Accept: image/… | 6 × 567 | 1 × 200 |
| V3 | + Referer: 来源文章页 | 6 × 567 | 1 × 200 |
| V4 | + Accept-Language / Sec-Fetch-* | 6 × 567 | 1 × 200 |
| V5 | HEAD(同 V4 请求头) | 6 × 567 | 1 × 200 |
| 合计 | 6 种 × 7 条 URL | 36 × 567 | 6 × 200 |
第一次实验里,H1 的 36 个响应都没有记录到 Content-Type、Content-Length 与 Server 头,读取字节数为 0(当时未读取 567 的错误响应体;复检见下节);C1 的 6 个响应均为 image/png、Content-Length 12,017 字节、Server 为 openresty。同一探测方法在对照主机上工作正常,说明 567 不是脚本本身的错误。
浏览器对照:这次也没有复现“浏览器可显示”
| 检查 | 结果 | 说明 |
|---|---|---|
| Chromium 直接打开图片 URL | HTML 403 挑战页 | 页面文本为 “http 403.” 加一串数字,不是图片 |
| Chromium 打开来源文章页 | Logo 与正文配图显示占位图 | 同机同网,站点自身图片未渲染 |
| Python 36 次请求 | 全部 567 | 含完整浏览器头与 HEAD |
第 83 期曾记录“浏览器通常能显示,脚本拿不到字节”。本期在 2026-11-06 18:43–18:44 的复检中,直接访问与来源页渲染都没有显示这些图片。两次观察不一致,说明这类现象会随网络出口、时间或 CDN 策略变化,不能用一次“浏览器能看”就判定图片对所有人都可用。
跨日复检:2026-11-07 00:40–00:42
在第一次实验约 6 小时后(跨过午夜),对同一批 6 条 H1 URL 和 1 条 C1 URL 重跑同样的 6 种请求。42/42 的状态不变:H1 仍是 36/36 = 567,C1 仍是 6/6 = 200。浏览器直接打开同一图片 URL,仍是 HTML 403 挑战页。
这次复检改了错误响应读取:第一次遇到 567 时只记录状态,没有读响应体与响应头;复检会读取 HTTPError 的 body 与 Content-Type。因此 H1 的 36 个 567 响应这次带回 29–30 字节的 text/markdown body(GET;HEAD 为 0 字节),内容是 “http 403.” 加一串数字。数字每次请求可能不同;不能据此推断 CDN 策略,只能说明 567 不是空响应。
| 项 | 2026-11-06 18:42–18:44 | 2026-11-07 00:40–00:42 |
|---|---|---|
| H1 状态 | 36 × 567 | 36 × 567 |
| C1 状态 | 6 × 200 | 6 × 200 |
| H1 响应体 | 未读取(记 0 字节) | 29–30 B,text/markdown(GET) |
| C1 响应体 | 12,017 B,image/png | 12,017 B,image/png |
| 浏览器直接访问 | HTML 403 挑战页 | HTML 403 挑战页 |
结论:在这约 6 小时的跨日窗口里,567/200 的分层是稳定的;变化的是我们这次终于读到了 567 的响应体。不能把“这次读到 body”写成“服务器行为变了”。
主机与站点分布
| 主机 | 站点数 | 图片 URL | 裸请求状态 |
|---|---|---|---|
| H1 | 6 | 149 | 567 |
| C1 | 1 | 39 | 200 |
| 合计 | 7 | 188 | — |
36 个页面来自 10 个站点,其中 7 个站点至少有一张站外图;H1 的 149 张图分布在 6 个站点,说明这不是单个页面的偶发问题。E16 的 39 张无扩展名图片全部来自 C1,本次可正常取回。
这意味着什么
- 567 不等于图片损坏。 它是一个 HTTP 响应;同一 URL 可能在别的网络、别的客户端可用。公开报告只写“本机取不到字节”。
- 567 也不等于请求头问题。 至少在本机视角,UA、Accept、Referer、Sec-Fetch 与 HEAD 都不是开关。
- 验收要两列分开记。 “脚本请求状态”和“浏览器实际渲染”是两件事;只测其中一个都会误判。
- 站外图片要有退路。 CDN 域名、边缘策略或区域访问变化会直接影响页面;关键图片应可自托管或准备替代源。
- 别用 HEAD 代替 GET。 HEAD 通过不代表 GET 能取到字节;本次两者在 H1 上一致,但不构成通用规则。
与图片交付、alt 研究的关系
第 83 期统计出 188 张站外图(37.7%),第 85 期抽检 30 张时 13 张返回 567。本期把“567 是不是请求头造成的”单独做了对照:6 条 URL × 6 种请求全部 567,且浏览器也没有渲染。三项放在一起,更稳妥的结论是:站外图片的可用性需要在真实浏览器里逐页确认,不能从扩展名或单次脚本请求推断。
局限
- 单主机、小样本:1 个 567 主机、6 条 URL、6 种请求;不是主机内分布,也不是行业基准。
- 单网络出口、两个时间窗:2026-11-06 18:42–18:44 与 2026-11-07 00:40–00:42,间隔约 6 小时;未做 24 小时以上、多地区或换出口复测。
- 浏览器对照只有一台 Chromium:不能代表其他浏览器、设备或登录状态。
- 未带站点会话:没有 Cookie、登录态或站点内跳转链;只测了 Referer。
- 匿名:公开 CSV 用 H1/C1 与 sample_id,不公开主机名与完整 URL,无法逐条外部复现。
数据与复算
匿名数据:equipment-image-cdn-header-response-2026.csv(42 行 × 12 列:主机、站点、变体、方法、状态、Content-Type、长度、读取字节、Server、错误与时间)。仓库内为 docs/research/2026-11-image-cdn-header-response.csv。
跨日复检数据:equipment-image-cdn-header-recheck-2026.csv(42 行 × 12 列,2026-11-07 00:40–00:42);equipment-image-cdn-header-compare-2026.csv(42 行 × 11 列,T0/T1 状态与读取字节对照)。仓库内为 docs/research/2026-11-image-cdn-header-recheck.csv 与 2026-11-image-cdn-header-compare.csv。
探测脚本:scripts/image_cdn_header_probe.py;单元测试 scripts/test_image_cdn_header_probe.py(无网络,12 项,覆盖 6 组请求头与 6 类响应判定)。运行:
python -m unittest scripts.test_image_cdn_header_probe
python scripts/image_cdn_header_probe.py --url <图片 URL> --page-url <来源页> --out response.csv
配套:文章页图片交付 pilot、图片清单检查器、文章页图片属性 pilot。
数据来源与口径
- 页面与图片 URL:第 83 期缓存的 36 个文章页原始 HTML(2026-11-03 抓取,10 站)。
- 发现与实验:2026-11-06 18:42–18:44,Python urllib,42 次请求,1.2 秒间隔。
- 浏览器对照:2026-11-06 18:43–18:44,本机 Chromium,直接访问与来源文章页各一次。
- 跨日复检:2026-11-07 00:40–00:42,同一 7 条 URL、6 种请求,1.2 秒间隔;浏览器直接访问一次。
- 状态码按实际返回记录;567 为非标准码,不归因于具体 CDN 策略。