Google Ads 是一个为曝光付费的竞争场域,搜索结果页顶部的付费结果会准确告诉你:哪些竞争对手愿意为每个查询出价。那些广告位是公开的:任何人都能执行一次搜索,读取你的对手摆在同一批受众面前的标题、显示 URL 和文案,而这批受众正是你也在争取的。当你跨目标关键词大规模采集这些数据时,它就成了可供你采取行动的广告情报。

本指南将向你展示如何分析竞争对手的 Google Ads:针对一份关键词列表,通过 Crawling API 采集 Google SERP 上的付费结果,解析每条广告的标题、显示 URL 和文案,然后弄清楚哪些竞争对手对哪些词出价。我们将整个演练严格限定在任何搜索者都能看到的公开广告数据上,而临近结尾的合规性章节并非套话,所以在你把它指向真实流量之前,请先读一读。

你将构建什么

一个 Python 脚本,它接收一份目标关键词列表,将每个关键词作为一次公开的 Google 搜索通过 Crawling API 执行,并为页面上每条付费广告提取一条结构化记录。Crawling API 内置的 Google SERP 抓取器会返回已解析好的广告,所以对每条广告你都能拿到这些字段:

  • 位置 该广告在付费结果中的排名,从顶部往下计数。
  • 标题 广告标题,即广告主撰写的那段加粗可点击文本。
  • 显示 URL 标题下方显示的可见目标地址,也就是竞争对手的品牌。
  • 描述 广告文案,即一两行的营销信息和行动号召。
  • 站内链接 一些广告主在主广告下方附加的额外深层链接。

从这里出发,你把按关键词得到的结果汇总成一份简单的竞争对手视图:哪些品牌在哪些关键词上投放广告,以及投放的频次。

为什么对 Google 发起普通请求会失败

如果你用脚本向某个 Google 搜索 URL 发起一次裸 HTTP 请求,你很少能得到你在自己浏览器里看到的那个页面。Google 用 JavaScript 渲染 SERP 的大部分内容,并密切监视自动化流量。一个看起来不像真实浏览器的请求,远在抵达广告标记之前就会撞上同意墙、CAPTCHA 或干脆被封锁,而广告位尤其是个性化的、且渲染较晚,所以一次原始抓取往往返回一个完全没有广告的页面。

因此,一个能用的 Google Ads 抓取器需要在同一个请求里满足两件事:一个被平台读作真实访客的 IP,以及一个能渲染页面的浏览器。你可以自己用无头浏览器加一池轮换住宅代理来拼凑这套方案,但让它们保持健康才是大部分工作。Crawling API 把两者折叠进一次调用:你把搜索 URL 发给它,它从一个受信任的住宅 IP 抓取并渲染页面,其 Google SERP 抓取器会返回已解析成结构化 JSON 的广告。

为什么 SERP 抓取器在这里有帮助

Google 的广告标记使用经过哈希处理、频繁轮换的类名,所以手写的 CSS 选择器经常失效。Crawling API 的 google-serp 抓取器在服务端解析页面,并交回一个干净的 ads 数组,于是你按名称读取字段,而不是去追逐每次重新部署都会改变的类名。你可以从 1,000 次免费请求开始,无需信用卡。

要提取的关键数据点

在写代码之前,值得先弄清楚每个字段告诉你什么,因为分析的质量只取决于你采集的字段。

  • 广告标题和描述。竞争对手的广告文案展示了他们认为有效的营销信息。留意反复出现的措辞、情感触发点,以及那些能赢得点击的行动号召。
  • 所投放的关键词。如果某个竞争对手的广告在某个关键词上展示,说明他们正在为它出价,这是该词对他们能带来转化的强烈信号。
  • 广告位置与排名。一个始终占据付费首位的广告主,要么出价激进,要么投放着高质量广告,两者都值得弄懂。
  • 显示 URL 与落地 URL。显示 URL 标明了竞争对手是谁;目标地址展示了他们如何转化流量,从页面设计到优惠方案。
  • 广告附加信息。站内链接、附加说明文字和结构化片段让广告更大、更具吸引力。记下谁在用它们以及怎么用。

前置条件

在写任何代码之前,你需要准备好几样东西。它们都花不了多久。

基础 Python。你应当能自如地编写和运行一个 Python 脚本,并用 pip 安装软件包。如果解析 JSON 输出对你来说还很新,我们的用 Python 抓取网站指南涵盖了本教程默认你已掌握的基础。

Python 3.8 或更高版本。python --version 确认你的版本。如果还没有,请从 python.org 安装,或通过 Anaconda 这类发行版安装。

一个 Crawlbase 账户和 token。注册、打开你的仪表盘,复制你的请求 token。你的前 1,000 次请求是免费的。SERP 抓取器会渲染页面,所以请使用你常规的(JavaScript)请求 token。把 token 当作密码对待:它用于认证你的请求,所以不要把它放进版本控制。

搭建项目

安装官方的 Crawlbase Python 库,它把 Crawling API 及其 SERP 抓取器封装进一个小巧的客户端。

bash
python --version

python -m venv ads_env
source ads_env/bin/activate

pip install crawlbase

在 Windows 上,请用 ads_env\Scripts\activate 替代那行 source 命令来激活环境。crawlbase 包为你提供一个 CrawlingAPI 客户端,它发送请求、应用 Google SERP 抓取器并返回解析后的响应,于是你不必自己为广告写任何 HTML 解析。

第 1 步:抓取一个 SERP 并取出广告

先从获取单个关键词的广告开始。写一个 scrape_google_ads() 函数,它构建搜索 URL,通过 Crawling API 用 google-serp 抓取器发送,检查状态,并返回解析后的 ads 数组。

python
import json
from urllib.parse import quote
from crawlbase import CrawlingAPI

API_TOKEN = "YOUR_CRAWLBASE_TOKEN"  # replace with your token
crawling_api = CrawlingAPI({"token": API_TOKEN})

def scrape_google_ads(query):
    url = f"https://www.google.com/search?q={quote(query)}"
    options = {"scraper": "google-serp"}
    response = crawling_api.get(url, options)

    if response["headers"]["pc_status"] != "200":
        print(f"Failed to fetch '{query}'")
        return []

    parsed = json.loads(response["body"].decode("latin1"))
    return parsed.get("body", {}).get("ads", [])

if __name__ == "__main__":
    ads = scrape_google_ads("project management software")
    print(f"Found {len(ads)} ads")
    print(json.dumps(ads[:1], indent=2, ensure_ascii=False))

SERP 抓取器返回一个 JSON 信封。你读取两样东西:response["headers"]["pc_status"] 是底层 Google 抓取的状态,response["body"] 是解析后的负载,你对它解码并用 json.loads 加载。守住 pc_status 意味着封锁或同意墙会以明确的失败浮现出来,而不是把一个空页面喂进你的分析。广告位于 body.ads 之下,已被拆分成一条条记录,所以像 "project management software" 这样的单个关键词会以一个你可以检查的列表返回。运行脚本,你应当能看到一个计数以及打印出来的第一条广告,这在你扩大规模之前确认了抓取和解析都正常工作。

Crawlbase Crawling API

那个 pc_status 读到 200,且 ads 数组返回时已填充,是因为该请求以一个真实访客的身份抵达了 Google,且页面已完全渲染。Crawling API 从一个轮换住宅 IP 抓取每个 SERP,像浏览器那样渲染它,其 Google SERP 抓取器把已解析好的广告交给你,于是你免去了运行一支无头浏览器舰队、采购代理池以及针对 Google 哈希类名编写选择器的工作。先在免费额度上把它指向一个公开的搜索 URL。

第 2 步:规范化广告字段

解析后的广告已经给了你所需的一切,但把每条广告拍平成一条一致的记录是值得的,这样分析步骤就不必去深入嵌套的键里取值。写一个小巧的 parse_ads() 函数,从每条广告中取出标题、显示 URL、描述、目标地址以及任何站内链接,并打上产生它的关键词标记。

python
def parse_ads(query, ads):
    records = []
    for ad in ads:
        site_links = [
            {
                "title": link.get("title"),
                "url": link.get("url"),
            }
            for link in ad.get("siteLinks", [])
        ]
        records.append({
            "keyword": query,
            "position": ad.get("position"),
            "title": ad.get("title"),
            "displayUrl": ad.get("displayUrl") or ad.get("url"),
            "description": ad.get("description"),
            "destination": ad.get("url"),
            "siteLinks": site_links,
        })
    return records

现在每条记录都带着它来自的 keyword、广告的 positiontitle 标题、displayUrl(可见的品牌,若显示字段缺失则回退到目标地址)、description 文案、真实的 destination URL,以及任何 siteLinks 的拍平列表。给每条广告打上关键词标记,正是让后续分析成为可能的关键:它让你能够跨许多关键词按竞争对手对广告分组,而不会弄丢每条广告各自出现在哪个词上。

显示 URL 是你区分竞争对手的键

显示 URL(或其注册域名)是识别谁在一条广告背后最可靠的方式。标题和文案随广告系列而变,但品牌域名是稳定的,所以在你统计谁对什么出价时,请按 displayUrl 分组。

第 3 步:跑一份关键词列表并分析竞争对手

现在把它串起来。遍历你的目标关键词,为每个抓取并解析广告,收集每一条记录,然后把这些记录汇总成一份竞争对手视图。用一段短暂的睡眠为循环控速,这样你就不会一个接一个地连发请求。

python
import json
import time
from urllib.parse import quote, urlparse
from collections import defaultdict
from crawlbase import CrawlingAPI

API_TOKEN = "YOUR_CRAWLBASE_TOKEN"
crawling_api = CrawlingAPI({"token": API_TOKEN})

KEYWORDS = [
    "project management software",
    "crm for small business",
    "time tracking app",
]

def scrape_google_ads(query):
    url = f"https://www.google.com/search?q={quote(query)}"
    response = crawling_api.get(url, {"scraper": "google-serp"})
    if response["headers"]["pc_status"] != "200":
        print(f"Failed to fetch '{query}'")
        return []
    parsed = json.loads(response["body"].decode("latin1"))
    return parsed.get("body", {}).get("ads", [])

def parse_ads(query, ads):
    return [
        {
            "keyword": query,
            "position": ad.get("position"),
            "title": ad.get("title"),
            "displayUrl": ad.get("displayUrl") or ad.get("url"),
            "description": ad.get("description"),
            "destination": ad.get("url"),
        }
        for ad in ads
    ]

def domain_of(record):
    target = record["destination"] or record["displayUrl"] or ""
    return urlparse(target).netloc or target

def main():
    all_ads = []
    for keyword in KEYWORDS:
        ads = scrape_google_ads(keyword)
        all_ads.extend(parse_ads(keyword, ads))
        print(f"{keyword}: {len(ads)} ads")
        time.sleep(2)

    competitors = defaultdict(list)
    for record in all_ads:
        competitors[domain_of(record)].append(record["keyword"])

    report = {
        domain: {
            "adCount": len(keywords),
            "keywords": sorted(set(keywords)),
        }
        for domain, keywords in competitors.items()
    }

    with open("competitor_ads.json", "w", encoding="utf-8") as f:
        json.dump({"ads": all_ads, "competitors": report},
                  f, ensure_ascii=False, indent=2)
    print(f"Saved {len(all_ads)} ads from {len(report)} competitors")

if __name__ == "__main__":
    main()

python competitor_ads.py 运行完整脚本。它为 KEYWORDS 中的每个关键词抓取广告,把它们拍平成记录,然后用 defaultdict 按竞争对手域名把每条记录分组,构建出一份报告:每个品牌投放了多少条广告、跨哪些关键词。输出写入 competitor_ads.json,其中既有原始广告记录,也有汇总后的竞争对手视图。往 KEYWORDS 里添加更多词,同样这两个函数就能处理其余部分;分析会随你的列表一起增长。

输出长什么样

你会得到一个结构化对象,包含解析后的广告和一份竞争对手摘要,可以直接载入电子表格、笔记本或数据库做更深入的分析。

json
{
  "ads": [
    {
      "keyword": "project management software",
      "position": 1,
      "title": "Project Management Tool | Plan, Track and Ship Faster",
      "displayUrl": "https://www.example-pm.com/",
      "description": "Run every project in one place. Free 14-day trial, no card required.",
      "destination": "https://www.example-pm.com/trial"
    }
  ],
  "competitors": {
    "www.example-pm.com": {
      "adCount": 2,
      "keywords": ["crm for small business", "project management software"]
    }
  }
}

competitors 区块正是情报所在之处:它一眼就告诉你哪些品牌对你的哪些词出价,以及每个品牌出现在你所追踪关键词中的多少个上。一个在多个关键词上出现的竞争对手是在广泛投入;一个在你最高价值的词上占据首位的对手,则值得你更仔细地看看他们的文案和落地页。

跨关键词与地区扩展规模

一份小小的关键词列表只是演示;一项真实的工作会追踪数十个词,往往跨多个地区,并按计划重跑以捕捉新进入者。形态保持不变:构建每个搜索 URL,通过 Crawling API 用 SERP 抓取器抓取它,并解析广告。再加上几样东西就能让它达到生产可用。

  • 本地化 SERP。广告竞价因国家而异,所以在搜索 URL 上加 &gl=us&hl=en(或换成另一个国家和语言),以采集该市场中的搜索者会看到的广告。
  • 为循环控速。在请求之间保留那段短暂的睡眠,而不是一个接一个地连发。把一份很大的关键词列表摊开,而不是在一个紧凑的循环里猛攻 Google。
  • 安排重跑。广告文案和出价者每周都在变,所以一次每周运行能把一次性的快照变成一条你可以随时间追踪的趋势。

Crawlbase 默认提供每秒最多 20 个请求,对一个有节奏的关键词追踪器来说绰绰有余,而 API 返回的任何 5XX 响应都是免费的,所以重试一个被封锁的 URL 不花你一分钱。如果你更愿意把自己的流量路由经过一个轮换池,Smart AI Proxy 以一个即插即用的端点为你提供同样的住宅轮换。若想了解专门围绕 Google 的解析与防封锁套路,参见如何轮换代理以抓取 Google 搜索结果以及如何在抓取 Google 时绕过 CAPTCHA

把抓取与官方透明度来源结合起来

抓取实时 SERP 会告诉你此刻针对你确切的关键词正在投放什么,这是你用任何其他方式都拿不到的数据。要让画面更完整,请把它与 Google 自己的免费工具,即 Google Ads Transparency Center 配对使用。它让你能查找一个广告主,看到他们在 Google 网络上正在投放的广告、使用的格式以及定向的地区。它是官方来源,所以是深入研究一个已知竞争对手创意的正确去处。

两种方法相辅相成:抓取你的关键词列表,弄清楚谁在每个词上竞争、他们的文案在上下文中读起来如何,然后对那些重要的品牌打开 Transparency Center,看看他们更广的广告系列覆盖面。除了 Google 自己的工具,SEMrush、SpyFu 和 Ahrefs 这类付费平台会估算广告支出和历史关键词覆盖,这对趋势研究有用,但不如你自己读实时 SERP 那样精确。

抓取 Google Ads 数据是否被允许,取决于 Google 的服务条款、你所在的司法管辖区,以及你拿这些数据做什么。Google 的条款对其搜索服务的自动化访问设有限制,所以无论你的工具多么谨慎,抓取都可能与那些条款相抵触。广告位本身是公开的,任何人执行同样的搜索都能看到它们,但 "公开" 并不等同于 "不受限制"。这里的任何代码都不会改变 Google 的条款;它只是让技术部分能跑通。请阅读 Google 的条款及其 robots.txt,并把两者都当作你采集范围的边界。

有几条值得坚守的准则。只采集公开的广告数据:任何搜索者无需账户就能在结果页上看到的标题、显示 URL、描述、位置和站内链接。把你的请求量保持得足够低,以免给 Google 的服务器造成压力,并为你的爬取控速,而不是全速狂奔。不要抓取任何登录墙之后的内容,不要采集个人数据,也不要把竞争对手受版权保护的广告创意当作你自己的来重新发布。你是在收集竞争情报以指导你的策略,而不是在搭建别人广告系列的镜像。

在存在官方来源的地方,优先用它。Google 的 Ads Transparency Center 是一种被认可的方式,用于研究某个广告主正在投放的广告,当你想深入了解某个特定竞争对手、而非实时读取你自己的关键词列表时,它是正确的路径。本指南刻意被限定在公开、可见的广告结果上,因为那正是让这项工作站得住脚的边界。如果你的项目需要的不止于此,那么一份官方数据协议或某个获得授权的广告情报平台才是正确的路线,而不是一个更聪明的抓取器。

回顾

核心要点

  • 广告位是公开的信号。针对你关键词的付费结果展示了哪些竞争对手在出价、他们说了什么、把流量送往哪里,大规模采集后便成为广告情报。
  • SERP 抓取器替你做解析。通过 Crawling API 用 google-serp 抓取器发送每个搜索 URL,并从 body.ads 读取广告,而不必针对 Google 的哈希类名编写选择器。
  • 给每条广告打上关键词标记。把关键词一路带到每条记录上,正是让你能按竞争对手域名对广告分组、看清谁对哪些词出价的关键。
  • 按显示 URL 分组。品牌域名是统计竞争对手的稳定键;标题和文案会变,域名不会。
  • 把抓取与 Transparency Center 配对。抓取实时 SERP 获取关键词覆盖面,然后用 Google 官方的 Ads Transparency Center 深入了解某个特定广告主,并始终只停留在公开数据上。

常见问题

为什么一次普通请求返回的 Google 页面上没有广告?

Google 用 JavaScript 渲染 SERP 的大部分内容(包括广告位),并按请求做个性化处理,同时它会封锁看起来不像真实浏览器的流量。一次裸 HTTP 调用往往得到一面同意墙、一个 CAPTCHA,或一个完全没有广告的精简页面。通过 Crawling API 抓取(它使用轮换住宅 IP 并渲染页面)能让请求看起来像一个普通访客,于是广告确实在场,而其 SERP 抓取器会把它们以已解析好的形式返回。

我能从一个 Google SERP 提取哪些广告字段?

Google SERP 抓取器返回一个 ads 数组,其中每条广告都带有位置、标题(即标题文本)、显示 URL、描述(即文案)、目标 URL 以及任何站内链接。本教程把它们拍平成每条广告一条记录,并打上产生它的关键词标记,这足以分析文案、位置以及哪些竞争对手对哪些词出价。

我如何找出哪些竞争对手对某个关键词出价?

把每个目标关键词作为一次搜索运行,收集广告,然后按竞争对手域名(由显示 URL 或目标 URL 推导得出)对记录分组。一个为某关键词出现的品牌就是在为它出价。把这些分组在你整份关键词列表上汇总起来,你就得到一份按竞争对手呈现的覆盖面视图,这正是本指南分析的核心。

两者都用。Transparency Center 是 Google 官方的工具,用于查看某个广告主在整个网络上投放的广告,所以它非常适合深入研究一个已知竞争对手的创意。抓取实时 SERP 来覆盖你自己的关键词列表,会告诉你此刻谁在每个词上竞争、他们的文案在上下文中读起来如何,而这是 Transparency Center 不会直接给你的。它们回答的是不同的问题。

依靠轮换住宅 IP,让请求来自许多真实用户的地址;渲染页面,好让广告加载出来;并为你的请求控速,而不是在一个紧凑的循环里连发。Crawling API 替你处理轮换和渲染;如果你自建技术栈,那些就是需要做对的部分。在每个响应上读取状态,也让你能在 Google 一开始返回挑战时就立刻退避。

我能随时间追踪广告的变化吗?

能。因为每次运行都会写出一份以关键词和竞争对手域名为键的结构化快照,所以安排一次每周运行并对比这些快照,就能让你看到新进入者、退出的广告主,以及文案或位置上的变化。若想更广泛地使用这类竞争数据,参见我们关于运用网页抓取做价格情报的指南。

开始构建

大规模爬取任何站点,无需与基础设施对抗。

Crawlbase 负责处理代理、指纹和 CAPTCHA,让你的团队专注于交付数据流水线,而非维护爬取管道。1,000 次请求免费,无需信用卡。

自助开通 · 无需销售通话 · 提供企业级爬取量