Use Cases

带有验证码处理的广告验证工作流程

广告验证脚本卡住,十有八九不是解析逻辑写错了,而是发布商页面弹出了验证码。广告验证团队每天要访问成百上千个页面,核对广告位置、品牌安全和地域定向是否达标,而很多发布商站点正好用验证码拦截这类批量访问。用 CaptchaAI 的 API 自动识别这些验证码,验证流水线就不会在半路断掉。

广告验证到底在查什么,验证码又是怎么挡路的

检查项 具体内容 验证码为什么会挡路
广告位置 广告是否展示在首屏可见区域? 自动化访问页面会触发机器人检测
品牌安全 广告旁边不能出现违规或有害内容 批量 URL 核查在行为上很像抓取
可见度 广告是不是真的被用户看到? 无头浏览器容易被 Cloudflare 标记
地域定向 广告投放地区是否正确? 代理流量本身就容易触发验证码
竞品监控 竞争对手投的是什么广告? 高频率的广告查询看起来像滥用行为

用 Python + CaptchaAI API 自动识别验证码,跑通广告位检测

下面这段脚本会访问发布商页面,遇到 reCAPTCHA 就调用 CaptchaAI 的 in.php / res.php 接口拿到 token,再把识别结果和检测到的广告标签、品牌安全关键词一起写进报告:

import requests
import time
import re
import json
import os
from datetime import datetime

API_KEY = os.environ["CAPTCHAAI_API_KEY"]


def solve_captcha(method, params):
    params["key"] = API_KEY
    params["method"] = method

    resp = requests.get("https://ocr.captchaai.com/in.php", params=params)
    if not resp.text.startswith("OK|"):
        raise Exception(resp.text)

    task_id = resp.text.split("|")[1]
    for _ in range(60):
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY, "action": "get", "id": task_id,
        })
        if result.text == "CAPCHA_NOT_READY":
            continue
        if result.text.startswith("OK|"):
            return result.text.split("|", 1)[1]
        raise Exception(result.text)
    raise TimeoutError()


def verify_ad_placement(url, session):
    """Verify ad placement on a publisher page."""
    resp = session.get(url)

    # Solve CAPTCHA if present
    match = re.search(r'data-sitekey=["\']([A-Za-z0-9_-]+)["\']', resp.text)
    if match:
        token = solve_captcha("userrecaptcha", {
            "googlekey": match.group(1),
            "pageurl": url,
        })
        resp = session.post(url, data={"g-recaptcha-response": token})

    html = resp.text

    # Check for ad elements
    result = {
        "url": url,
        "timestamp": datetime.utcnow().isoformat(),
        "ads_found": [],
        "brand_safety": True,
        "captcha_solved": match is not None,
    }

    # Detect ad tags
    ad_patterns = [
        (r'googletag\.pubads', "Google Ad Manager"),
        (r'doubleclick\.net', "DFP/DoubleClick"),
        (r'ad\.doubleclick', "DoubleClick"),
        (r'amazon-adsystem', "Amazon Ads"),
        (r'criteo\.com/.*\.js', "Criteo"),
    ]

    for pattern, name in ad_patterns:
        if re.search(pattern, html):
            result["ads_found"].append(name)

    # Brand safety check — flag problematic content
    safety_keywords = [
        "violence", "hate speech", "explicit",
        "gambling", "illegal",
    ]
    page_text = re.sub(r'<[^>]+>', '', html).lower()
    for keyword in safety_keywords:
        if keyword in page_text:
            result["brand_safety"] = False
            break

    return result


def run_verification(urls, output_file="verification_report.json"):
    """Run ad verification across multiple publisher URLs."""
    session = requests.Session()
    session.headers["User-Agent"] = (
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
        "AppleWebKit/537.36 Chrome/120.0.0.0"
    )

    results = []
    for i, url in enumerate(urls):
        try:
            result = verify_ad_placement(url, session)
            results.append(result)
            ads = ", ".join(result["ads_found"]) or "None"
            safe = "SAFE" if result["brand_safety"] else "UNSAFE"
            print(f"  [{i+1}/{len(urls)}] {url}: {ads} [{safe}]")
        except Exception as e:
            results.append({
                "url": url,
                "error": str(e),
                "timestamp": datetime.utcnow().isoformat(),
            })
            print(f"  [{i+1}/{len(urls)}] {url}: ERROR - {e}")

        time.sleep(2)

    with open(output_file, "w") as f:
        json.dump(results, f, indent=2)

    # Summary
    total = len(results)
    safe = sum(1 for r in results if r.get("brand_safety"))
    captchas = sum(1 for r in results if r.get("captcha_solved"))
    errors = sum(1 for r in results if "error" in r)

    print(f"\n  Total: {total} | Safe: {safe} | CAPTCHAs solved: {captchas} | Errors: {errors}")

    return results


# Publisher URLs to verify
publisher_urls = [
    "https://publisher1.com/article/tech-news",
    "https://publisher2.com/sports/latest",
    "https://publisher3.com/finance/markets",
]

run_verification(publisher_urls)

整个流程跑完会生成一份 JSON 报告,标出每个页面命中了哪些广告标签、是否触发了品牌安全关键词、验证码有没有被成功识别。

Cloudflare 防护下的发布商页面怎么处理

不少优质发布商都挂了 Cloudflare,你需要同时处理 Turnstile 和完整的 Cloudflare Challenge:

def handle_cloudflare(url, session):
    """Handle Cloudflare-protected publisher pages."""
    resp = session.get(url)

    if "cf-turnstile" in resp.text:
        match = re.search(r'data-sitekey=["\']([^"\']+)', resp.text)
        if match:
            token = solve_captcha("turnstile", {
                "sitekey": match.group(1),
                "pageurl": url,
            })
            return session.post(url, data={
                "cf-turnstile-response": token,
            })

    if resp.status_code == 403 and "cf-browser-verification" in resp.text:
        data = solve_captcha("cloudflare_challenge", {
            "pageurl": url,
            "proxy": "user:pass@proxy:port",
            "proxytype": "HTTP",
        })
        # Parse qa_session_cookie and use same proxy
        return data

    return resp

一个真实场景:出海广告主怎么用它做批量核查

国内做海外投放的广告运营团队,经常要抽查投给 Google Ads、DSP 的广告在境外发布商站点上展示成什么样——这些站点大多在美国、欧洲或东南亚,验证码几乎是标配。常见验证码类型分布:

  • 境外发布商站点:reCAPTCHA v2/v3、Cloudflare Turnstile
  • 国内发布商站点:GeeTest(极验)v3

CaptchaAI 支持 reCAPTCHA v2/v3、Cloudflare Turnstile/Challenge、GeeTest v3 等主流类型,一套 API 覆盖境内外大部分场景,不必为每种验证码单独接一家服务商。

如果一次要跑几千个发布商页面,按线程数计费的套餐比按次计费划算——该选哪一档,看你的页面并发量,而不是总的验证码次数:

套餐 月费 线程数 适合场景
ADVANCE $90 50 中等规模出海广告核查
CORPORATE $240 150 大规模多地区批量核查

每个线程内解决次数不限,量再大可以上更高档位的 VIP 系列。

常见问题

hCaptcha 这类验证码,CaptchaAI 能处理吗?

目前 CaptchaAI 不支持 hCaptcha 和 FunCaptcha(Arkose Labs)。已支持的主流类型包括 reCAPTCHA v2/v3、Cloudflare Turnstile 和 Challenge、GeeTest v3、图片和九宫格验证码等。选型之前先确认目标发布商用的是哪一种。

大批量核查发布商页面,应该选哪个套餐?

按并发线程数选,而不是按验证码数量,具体测算见上一节的出海场景。

视频广告的验证码要怎么处理?

这套方案主要针对展示广告和原生广告。视频广告验证通常需要真实渲染页面,建议配合 Selenium 或 Playwright 打开浏览器后再触发验证码识别。

按地区批量验证广告投放,要注意什么?

换成目标地区的代理再发起请求。CaptchaAI 的接口支持传入代理参数,识别结果会和你的地域定向保持一致,不会因为出口 IP 跟目标地区不符而验证失败。

大规模抓取发布商页面会有合规风险吗?

只核查自己投放或已获授权核查的广告位,遵守目标站点的 robots 协议和使用条款,就不属于违规抓取。国内团队做这类核查时,也要留意《网络安全法》《数据安全法》里关于自动化数据采集的相关要求。

相关指南

该文章已禁用评论。