

# 如何保存可供对比的 Bing 关键词排名快照

保存每个 Bing 排名时，都保持查询、国家、语言、设置、结果数量上限和观测时间一致。排名是结果在所采集样本中的位置编号。数字越小，表示结果越靠前。结果数量上限是每个查询最多保留的结果数。只对比上述各项均一致的快照。快照是一次已保存的运行记录。如果你的页面未出现在有数量上限的样本中，就记录为该样本中未见该页面。不要编造排名。不要声称整个 Bing 都没有该页面。

## 你保存的是什么

Actor 是用于采集数据的托管程序。本方法使用 [Google Search Scraper](https://apify.com/chronometrica/google-search-scraper) Actor，构建版本为1.0.15。Task 是已保存的输入预设。当前的 [Keyword Search Rank Snapshot](https://apify.com/chronometrica/google-search-scraper/examples/keyword-rank-snapshot) Task 仅提供起始输入，本身不会分析排名。

Actor 保存来源数据行。你需要按照下列步骤对比这些数据行。

构建版本1.0.15的 engines 列表可接受 Google、Bing、Brave 和 DuckDuckGo。本方法只接受 Bing。不要将 Google、Brave 和 DuckDuckGo 纳入这份台账。一条暂缓采用的 Google 处理路径返回了重定向地址，无法直接看出最终网站。这些地址不属于本方法认可的目标网址。

台账是记录快照的表格。这份台账不表示 Google Search Console 的平均排名，也不表示每个人看到的排名。

## 设置 Bing 输入

当前的 [Keyword Search Rank Snapshot](https://apify.com/chronometrica/google-search-scraper/examples/keyword-rank-snapshot) Task 保存了以下输入：

```json
{
  "queries": ["best CRM", "small business accounting software", "AI marketing tools"],
  "engines": ["google", "bing", "brave", "duckduckgo"],
  "maxResultsPerExecutedQuery": 20,
  "country": "US",
  "language": "en",
  "safeSearch": true,
  "includeSponsoredResults": false
}
```

设置 Bing 输入

替换整个 queries 列表。替换整个 engines 列表。首次检查时，使用1个你计划跟踪的查询。将 engines 设为 ["bing"]。将 maxResultsPerExecutedQuery 设为2。将 country 和 language 设为以后将重复使用的组合。保持 safeSearch 为 true。保持 includeSponsoredResults 为 false。

该输入没有扩展设置，也没有公开的页数限制字段。结果数量上限由 maxResultsPerExecutedQuery 指定。不要添加页数上限字段。

在请求中指定国家并不能消除个性化。个性化是指 Bing 仍可能向不同的人显示不同的结果。指定国家不能保证结果与每位当地用户看到的结果一致。

首次检查时，使用以下结构。将你的实际查询词填入 queries：

```json
{
  "queries": ["one intended phrase"],
  "engines": ["bing"],
  "maxResultsPerExecutedQuery": 2,
  "country": "US",
  "language": "en",
  "safeSearch": true,
  "includeSponsoredResults": false
}
```

设置 Bing 输入

只有确定以后会持续使用新的 country 和 language 组合时，才更改这些设置。此后每份快照都记录相同的值。

首次对比前，固定以下选项：

- 完全一致的查询文本
- country
- language
- safeSearch
- includeSponsoredResults
- maxResultsPerExecutedQuery

之后更改数量上限，可能会使结果呈现的顺序发生变化。之后更改结果读取方式，也可能产生同样的影响。对比时，保持采集范围相近。

## 读取每条结果数据

每行数据表示在1个搜索引擎、1个查询、1个结果页和1个位置上观测到的1条结果。Actor 可以在一次运行中保留多个查询，不会将这些查询合并为每个网站仅1行的数据。本方法要求每次运行只包含1个 Bing 查询。

以下是 [Google Search Scraper](https://apify.com/chronometrica/google-search-scraper) Actor 数据行中的字段，名称与原字段完全一致：

- runId
- country
- language
- safeSearch
- engine
- executedQuery
- page
- rankOnPage
- rank
- title
- canonicalUrl
- resultDomain
- snippet
- isSponsored
- advertiserDomain
- observedAt
- schemaVersion

rank 表示结果在该次运行所采集样本中的位置。rankOnPage 表示结果在该结果页上的位置。page 表示结果页的页码。

canonicalUrl 是 Actor 清理链接后保存的地址字符串。它是一个候选地址，并非经过核查的 HTML rel=canonical 链接，也不是原始 href 的完全复制。保持返回的字符串不变。这个字符串就是你的来源证据。

snippet 是搜索结果中的文本，不是目标网站的文章正文，也不能证实该网站上的某项说法。

isSponsored 表示该行是否为付费结果。自然搜索结果是非付费结果。将付费和非付费数据行分开。当 includeSponsoredResults 设为 false 时，不要将赞助结果行的排名视为自然搜索排名。

advertiserDomain 可能出现在赞助结果行中。它不表示另一个自然搜索排名。

数据行中的 country、language 和 safeSearch 是请求中指定的条件，不保证每个个性化结果都符合这些条件。

Actor 不会打开目标网站，不会移除所有多余的页面文本，不会核查引用，不会给销售表现评分，也不会安排下次运行。如果你需要检查目标网站，就需要自行检查。

## 读取运行摘要

OUTPUT 是运行摘要，与各条结果数据分开保存。两者都要读取。OUTPUT 使用以下字段：

- queriesRequested
- searchesCompiled
- executionsPlanned
- enginesSuccessful
- enginesFailed
- pagesAttempted
- pagesParsed
- resultsSaved
- engineStatusCounts
- engineResultCounts
- queryResultCounts
- stopReason

该 Actor 当前的一次 Bing 对照检查使用了查询词 Python asyncio documentation。Actor 尝试处理1个结果页，并成功解析该页。它保存了2行数据。2行都是直达 docs.python.org 的网址。engine 为 bing。executedQuery 与上述查询词完全一致。page 为1。其中1行的 rank 为1，另1行的 rank 为2。每行都有 observedAt。

该对照检查的 OUTPUT 如下：

```json
{
  "queriesRequested": 1,
  "searchesCompiled": 1,
  "executionsPlanned": 1,
  "enginesSuccessful": 1,
  "enginesFailed": 0,
  "pagesAttempted": 1,
  "pagesParsed": 1,
  "resultsSaved": 2,
  "engineStatusCounts": {"bing": {"ok": 1}},
  "engineResultCounts": {"bing": 2},
  "queryResultCounts": {"Python asyncio documentation": 2},
  "stopReason": "result_caps_reached"
}
```

读取运行摘要

已知的对照检查数据行字段值如下：

| 字段 | 对照检查值 |
| --- | --- |
| engine | bing |
| executedQuery | Python asyncio documentation |
| page | 1 |
| rank | 1和2 |
| canonicalUrl | 2个直达 docs.python.org 的网址 |
| observedAt | 每行都有 |

stopReason 的值为 result_caps_reached，表示运行已达到结果数量上限，并不表示 Bing 只有2条结果。

这次对照检查只核查了一个范围有限的 Bing 样本。它核查了网址、排名，以及保存的查询、结果页和时间。它没有测试 Google、Brave 或 DuckDuckGo，没有测试所有搜索运算符，也没有测试所有国家。它没有在之后再次观测排名，没有测量排名变化，没有测量流量，也没有提取目标网站内容。

如果 enginesFailed 不为0，不要声称目标不存在。查询失败时，不能将目标记为不存在。

空样本也不代表覆盖了整个 Bing。达到数量上限、失败和空结果，都只描述该次运行的情况。

## 按8个步骤对比快照

### 1. 选择目标和一份简短、固定的查询列表。

查看排名变化前，先确定目标。精确页面目标是事先声明的单个地址及其路径。域名目标是同一主机上符合认定条件且排名最靠前的页面。说明判断采用了哪一种目标定义。简短、固定的列表，是指每次重复使用相同的查询词。首次检查仍只使用1个查询词，且只使用 Bing。添加其他查询词时，必须将其作为独立的固定行，并使用相同的设置。

范围有限的 Bing 台账不报告 Google Search Console 的平均排名，也不报告每个人看到的排名。

### 2. 固定使用 Bing，并锁定样本设置。

将 Task 的引擎列表替换为 engines ["bing"]。首次检查时，将示例查询替换为1个你计划跟踪的查询。在这次试运行中，将 maxResultsPerExecutedQuery 设为2。固定 country、language、safeSearch、includeSponsoredResults 和结果数量上限。

相同查询词在不同国家产生的快照不同。开启和关闭安全搜索产生的快照不同。数量上限为2和为10的快照不同。在请求中指定国家，仍不能保证结果与每位当地用户看到的结果一致。

### 3. 检查成功返回的数据行和 OUTPUT。

保留每条成功返回的数据行中的 executedQuery、rank、rankOnPage、page 和 observedAt。在这些数据旁保留 OUTPUT 中的各项计数和 stopReason。当前的小规模对照检查在第1个结果页上得到了2个带排名的直达网址。这次对照检查没有测量你的页面的排名变化。

如果查询失败，不要将目标记为不存在，而应保存为 source_failed。

### 4. 按预先确定的规则匹配目标。

对于精确页面，按你事先声明的地址和路径规则进行比对。保留返回的 canonicalUrl。不要更改返回的字符串。

对于域名，匹配指定的主机。在该主机符合认定条件的自然搜索结果行中，保留最小的 rank。这个最小值就是该域名在样本中观测到的最佳排名。

不要因为公司名称相似就合并结果。不要合并不同子域名的结果。不要合并跟踪重定向结果，除非你已检查该重定向并认可其目标地址。如果无法确认身份，状态应为 unresolved_target。

### 5. 保存1个有效状态。绝不保存虚假排名。

当目标与某行匹配时，使用 observed_rank。有用的样本应来自一次已完成且成功的运行，并记录了数量上限。如果这样的样本中没有目标，使用 not_seen_within_cap。如果采集失败，使用 source_failed。如果无法判断某行是否为目标，使用 unresolved_target。

不要使用0，也不要使用 cap + 1。这些数字看起来像排名，但并非观测到的排名。

试运行的数量上限为2时，未找到目标应记为上限2以内的 not_seen_within_cap。该页面可能出现在更后面的位置。真实排名仍然未知。以后固定使用任何更大的上限时，也适用同一规则。

### 6. 之后使用相同输入再次运行。

当你决定投入这笔预算时，用固定的输入再次运行。将新快照保存为一条[新的观测记录](/zh-Hans/articles/%E6%90%9C%E7%B4%A2%E7%BB%93%E6%9E%9C%E5%90%88%E5%B9%B6-%E4%BF%9D%E7%95%99%E6%9F%A5%E8%AF%A2%E4%B8%8E%E6%8E%92%E5%90%8D%E8%AF%81%E6%8D%AE/)。不要覆盖旧记录。

Task 本身不会监测排名。定时运行需要你另行设置。对比时，使用相同的查询和目标规则。使用相同的 country、language 和 safeSearch 值。使用相同的赞助结果设置，并保持采集范围相近。

如果数量上限发生变化，就不能称这对快照具有可比性。如果结果读取方式发生变化，也不能称这对快照具有可比性。

### 7. 只有2个排名都已知时，才计算变化。

排名变化用简单的减法计算。排名变化 = 旧排名 - 新排名。结果为正数，表示新排名的数字更小。该结果在新样本中的位置比在旧样本中更靠前。

不要将 not_seen_within_cap 纳入减法计算。source_failed 和 unresolved_target 也不能纳入。不要将未知值与真实排名一起计算平均值。不要将0或 cap + 1这类替代数字纳入平均值。

样本中顺序的变化，不能证明流量发生了变化，不能证明销售发生了变化，也不能证明变化是由内容修改引起的。

### 8. 交付台账，仅对已知且可比的数据作比较。

为每个查询与目标规则的组合建立1行台账。记录来源运行、查询条件、数量上限、状态和对比说明。将 Google 和其他引擎的数据另行保存，不要在这里对它们作出结论。

最后给出1组条件匹配的快照对比，或注明尚无法确定对比结果。不要用猜测的排名填补空缺。

## 虚构的排名台账

下表为原创虚构示例，用于说明各类状态。它不是 Actor 的运行结果，也不是上文的 Bing 对照检查。虚构的目标页面为 https://garden.example/guide. 虚构的域名为 garden.example。S1 是较早的快照。S2 是较新的快照。Q1 的2份快照使用相同的 Bing 设置，数量上限都为前10条结果。试运行的数量上限为2，采集范围不同。不要混用这些上限。示例未提供日期，因此不显示日期。

Q1 对比的是指定的指南页面。S1 观测到排名为7，S2 观测到排名为4。2个排名都来自数量上限相同的前10条结果样本。排名变化 = 7 - 4 = +3。按此定义，该页面在样本中的位置向前移动了3位。

Q2 使用同一个精确页面，数量上限也同为10。S1 观测到排名为2。S2 的状态为上限10以内的 not_seen_within_cap。新排名未知，排名变化也未知。不要保存为11。该页面可能排在第10位之后，但你不知道它在更后面哪个位置。

Q3 使用同一个精确页面。示例未提供 S1 的排名和时间，因此 S1 仍为未知。S2 为 source_failed。无法进行对比。这不是排名下降。失败表示未能采集到新样本。

Q4 是1份域名快照，不是一组用于计算变化的快照。该域名上2个符合认定条件的页面，其自然搜索排名分别为3和8。如果目标是域名，观测到的最佳排名就是3。如果目标是指定的指南页面，该页面的排名可能为8。同时，该域名上的另一个页面可能排名为3。说明你使用了哪一种定义。不要将3报告为该精确页面的排名。

| 查询 | 目标规则 | S1 状态 | S2 状态 | 排名变化 | 可稳妥得出的结论 |
| --- | --- | --- | --- | --- | --- |
| Q1 | 精确页面 https://garden.example/guide | observed_rank 7 | observed_rank 4 | 7 - 4 = +3 | 一组已知排名，均来自数量上限相同的前十条结果样本 |
| Q2 | 精确页面，上限10 | observed_rank 2 | not_seen_within_cap 10 | 未知 | 不能记为排名11，也不能将排名变化记为2 - 11 |
| Q3 | 精确页面 | 未知 | source_failed | 未知 | 无法对比，不表示排名下降 |
| Q4 | 域名 garden.example，或指定的指南页面 | 1份快照：符合认定条件的排名为3和8 | 同一份快照，并非另一个时间点 | 无 | 域名的最小排名为3。指定指南页面的排名可能为8 |

有人可能会编造 Q2 的排名为11，再计算2 - 11 = -9。这个-9不是观测结果。将 Q1 的+3与这个虚假的-9一起计算平均值，会得到错误的汇总结论。先展示2个已知排名的对比，再展示仅在限定样本内未见目标的情况，以及来源采集失败的情况。计算任何平均值时，都应排除未知状态。

这些 S1 和 S2 值是教学台账中的状态，不是对照检查输出的原生排名字段。该对照检查只保存了排名1和2，并未测量变化。

## 下一步

保存1份 Bing 快照，记录完全一致的查询文本、国家、语言、safeSearch 设置、赞助结果设置和结果数量上限。记录1个有效的目标状态：已观测到排名、数量上限内未见目标、来源采集失败，或目标尚未确认。从 [Google Search Scraper](https://apify.com/chronometrica/google-search-scraper) Actor 和当前的 [Keyword Search Rank Snapshot](https://apify.com/chronometrica/google-search-scraper/examples/keyword-rank-snapshot) Task 开始。进行任何对比前，先将该 Task 改为只包含1个查询，并将 engines 设为 ["bing"]。

## 来源和延伸阅读

- [Google Search Scraper](https://apify.com/chronometrica/google-search-scraper)
- [Keyword Search Rank Snapshot](https://apify.com/chronometrica/google-search-scraper/examples/keyword-rank-snapshot)
- [https://www.reddit.com/r/SEO/comments/1dybuk8/any_tools_to_just_monitor_specific_keyword_ranking/](https://www.reddit.com/r/SEO/comments/1dybuk8/any_tools_to_just_monitor_specific_keyword_ranking/)
- [https://www.reddit.com/r/SEO/comments/1d5kve4/how_to_check_if_you_ranked_on_a_keyword/](https://www.reddit.com/r/SEO/comments/1d5kve4/how_to_check_if_you_ranked_on_a_keyword/)