如何在SERP爬取时避免被Google封锁

学习Google如何检测SERP刮刮机,以及如何避免使用住宅代理,现实头,随机计时,以及用代码示例重试策略的块.

如何在SERP爬取时避免被Google封锁

Google 如何检测 SERP 搜索器

Google大量投资保护其搜索结果不被自动访问. 在可以避开块之前,需要了解谷歌所使用的检测方法. 每一种方法都针对不同的信号,有效的SRP刮刮需要同时处理所有信号.

关于SERP刮刮结构的完整概述,请参见我们 带有代理指南的 SERP 刮刮。 。 。

基于IP的检测

第一道防线是IP分析. Google追踪每个IP地址的查询量,并标出超过正常人类搜索模式的查询量. 具体信号包括:

  • 请求频率 : 单个IP触发率限制的每分钟搜索数次以上
  • IP 声誉 : 已知数据中心IP范围立即接受审查
  • 地域不一致: 来自德国的IP 制作英语美国目标查询 升起旗帜
  • ASN分析: Google 识别属于主机供应商的IP块对ISP

浏览器指纹

除了IP地址之外,Google还审查自动化信号的请求本身:

信号谷歌检查红旗
用户代理浏览器和 OS 标识字符串缺少、过时或与其他信头不一致
接受信头内容类型偏好缺少接受语句或非标准接受值
TLS 指纹SSL/TLS 握手特性匹配已知 HTTP 库的指纹( 请求, urlib)
JavaScript 执行客户端脚本行为没有 JavaScript 执行( 无头检测)
Cookie 行为Cookie 验收和管理没有饼干或相同饼干模式的要求

更深入地审视这些技术,请读我们关于 反机器人系统如何检测代理。 。 。

行为分析

Google 分析各种请求的图案以检测自动化:

  • 请求时间 : 请求之间完全一致的间隔(例如,完全相隔3秒)是不自然的。
  • 查询模式 : 按字母顺序或以可预测的顺序拼写关键字看起来是自动的
  • 会话行为 : 真正的用户浏览多个页面,点击结果,并花时间阅读——刮刮器只是获取 SERP
  • 音量图案 : 来自相关实施伙伴的查询量突然激增,说明有协调的报废

反锁战略的三层

避免谷歌块需要分层处理. 单靠单一技术是不够的。

第1层:代理基础设施

你的代理选择是你的反封锁战略的基础. 代理哈特住宅代理 (c) 提供持续紧急救援系统报废所需的综合方案多样性和信任水平。

第2层:请求配置

每一个HTTP请求都必须看起来像是来自真正的浏览器. 信头、饼干和时机都需要现实

第3层:行为模式

您刮刮活动的总体模式必须模仿自然搜索行为. 这意味着随机的延迟,不同的查询序列,以及适当的请求卷.

住宅邻里:你的第一防线

最有影响力的单个变化是从数据中心切换到 住宅代办与谷歌的观点根本不同:

  • 住宅IP属于真正的ISP(Comcast, AT&T, BT, Deutsche Telekom),而不是云供应商
  • Google 无法屏蔽合法用户的 IP 区域
  • 每个IP都有其真实用户建立的浏览历史和声誉
  • 驻地实施伙伴支持在城市一级确定准确地点的地理目标

SERP 搜索的代理配置

import requests
# ProxyHat residential proxy with automatic rotation
PROXY_URL = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
session = requests.Session()
session.proxies = {
    "http": PROXY_URL,
    "https": PROXY_URL,
}
# Each request automatically gets a new residential IP
response = session.get(
    "https://www.google.com/search",
    params={"q": "best proxy service", "num": 10, "hl": "en", "gl": "us"},
    headers={
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.9",
        "Accept-Encoding": "gzip, deflate, br",
        "DNT": "1",
        "Connection": "keep-alive",
        "Upgrade-Insecure-Requests": "1",
    },
    timeout=15,
)

参见 代理数据文档 用于高级旋转和会话设置。

现实请求信头

不完整或不一致头条是刮刮机被阻断的最常见原因之一. 这里有一个完整,现实的 头集:

import random
# Rotate between realistic User-Agent strings
USER_AGENTS = [
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.3 Safari/605.1.15",
]
def get_headers():
    ua = random.choice(USER_AGENTS)
    headers = {
        "User-Agent": ua,
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.9",
        "Accept-Encoding": "gzip, deflate, br",
        "DNT": "1",
        "Connection": "keep-alive",
        "Upgrade-Insecure-Requests": "1",
        "Sec-Fetch-Dest": "document",
        "Sec-Fetch-Mode": "navigate",
        "Sec-Fetch-Site": "none",
        "Sec-Fetch-User": "?1",
        "Cache-Control": "max-age=0",
    }
    # Firefox has different Sec-Ch headers
    if "Firefox" not in ua:
        headers["Sec-Ch-Ua"] = '"Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"'
        headers["Sec-Ch-Ua-Mobile"] = "?0"
        headers["Sec-Ch-Ua-Platform"] = '"Windows"' if "Windows" in ua else '"macOS"'
    return headers
总是用当前浏览器版本更新您的用户代理字符串 。 2026年发送Chrome 90 User-Agent是一面直接的红旗.

限制费率和要求时间

您的请求模式与请求本身同样重要。 现已证明的时间安排战略如下:

随机延迟

从不使用请求之间的固定间隔 。 相反,随机化延迟来模仿人类的搜索行为:

import time
import random
def human_delay():
    """Generate a realistic delay between searches."""
    # Base delay: 3-8 seconds (normal browsing pace)
    base = random.uniform(3, 8)
    # Occasionally add longer pauses (simulating reading results)
    if random.random() < 0.15:
        base += random.uniform(10, 30)
    # Rare very short delays (rapid refinement searches)
    if random.random() < 0.05:
        base = random.uniform(1, 2)
    return base
# Usage in scraping loop
for keyword in keywords:
    result = scrape_serp(keyword)
    delay = human_delay()
    time.sleep(delay)

请求量准则

代理类型每个实施伙伴的安全请求/min最大并行IP
住所(轮换)1-2 (简体中文)无限制( 集合旋转)
住所(固定会议)每30人1人根据池大小
数据中心每60人1人受IP计数限制

处理 CAPTCHA 和块

即使有最好的预防措施, 你偶尔也会遇到障碍。 盖起你的刮刀来优雅地处理它们。

检测块

def is_blocked(response):
    """Check if Google has blocked or challenged the request."""
    # HTTP 429: Rate limited
    if response.status_code == 429:
        return "rate_limited"
    # HTTP 503: Service unavailable (temporary block)
    if response.status_code == 503:
        return "service_unavailable"
    text = response.text.lower()
    # CAPTCHA detection
    if "captcha" in text or "recaptcha" in text:
        return "captcha"
    # Unusual traffic message
    if "unusual traffic" in text or "automated queries" in text:
        return "unusual_traffic"
    # Empty or suspicious results
    if "did not match any documents" in text and len(text) < 5000:
        return "empty_suspicious"
    return None

重试策略

import time
import random
def scrape_with_retry(keyword, max_retries=3):
    """Scrape a SERP with automatic retry on blocks."""
    for attempt in range(max_retries):
        proxy_url = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
        proxies = {"http": proxy_url, "https": proxy_url}
        response = requests.get(
            "https://www.google.com/search",
            params={"q": keyword, "num": 10, "hl": "en", "gl": "us"},
            headers=get_headers(),
            proxies=proxies,
            timeout=15,
        )
        block_type = is_blocked(response)
        if block_type is None:
            return parse_results(response.text)
        if block_type == "rate_limited":
            # Exponential backoff
            wait = (2 ** attempt) * 5 + random.uniform(0, 5)
            print(f"Rate limited. Waiting {wait:.1f}s (attempt {attempt + 1})")
            time.sleep(wait)
        elif block_type == "captcha":
            # Switch to a new IP and wait
            print(f"CAPTCHA detected. Rotating IP and waiting...")
            time.sleep(random.uniform(10, 20))
        else:
            # Generic block: wait and retry
            time.sleep(random.uniform(5, 15))
    return None  # All retries exhausted

地理一致性

一项微妙但重要的反探测措施是确保你们请求参数的地域一致性:

  • 如果您的代理IP在美国, 请设定 gl=ushl=en
  • 将接受语言头匹配到目标区域
  • 使用用户代理字符串进行该国常见的OS/浏览器组合
  • 设定适合时区的请求时间

代用名词 地理目标特性 允许您从特定的国家和城市中选择代理,从而可以直接保持这种一致性。 更多地了解如何使用我们指南中针对位置的要求 刮刮而不受阻。 。 。

节点.js 反锁执行

以下是在节点(Node.js)实施的相应反封锁战略:

const axios = require('axios');
const cheerio = require('cheerio');
const { HttpsProxyAgent } = require('https-proxy-agent');
const USER_AGENTS = [
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0',
];
function getRandomUA() {
  return USER_AGENTS[Math.floor(Math.random() * USER_AGENTS.length)];
}
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
async function scrapeWithRetry(keyword, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const agent = new HttpsProxyAgent('http://USERNAME:PASSWORD@gate.proxyhat.com:8080');
    try {
      const { data, status } = await axios.get('https://www.google.com/search', {
        params: { q: keyword, num: 10, hl: 'en', gl: 'us' },
        headers: {
          'User-Agent': getRandomUA(),
          'Accept': 'text/html,application/xhtml+xml',
          'Accept-Language': 'en-US,en;q=0.9',
        },
        httpsAgent: agent,
        timeout: 15000,
        validateStatus: () => true,
      });
      if (status === 429) {
        const wait = Math.pow(2, attempt) * 5000 + Math.random() * 5000;
        console.log(`Rate limited. Waiting ${(wait/1000).toFixed(1)}s`);
        await sleep(wait);
        continue;
      }
      if (data.toLowerCase().includes('captcha')) {
        console.log('CAPTCHA detected. Rotating IP...');
        await sleep(10000 + Math.random() * 10000);
        continue;
      }
      return cheerio.load(data);
    } catch (err) {
      console.log(`Attempt ${attempt + 1} failed: ${err.message}`);
      await sleep(5000 + Math.random() * 10000);
    }
  }
  return null;
}

高级技术

查询随机

不按字母顺序或顺序刮去关键字 。 在每次运行前刷新您的关键字列表 :

import random
keywords = ["proxy service", "web scraping", "serp tracking", "seo tools"]
random.shuffle(keywords)
# Now scrape in random order
for kw in keywords:
    scrape_with_retry(kw)

谷歌搜索参数

使用这些参数获取干净的非个性化结果:

参数数值目的
pws0 个禁用个性化结果
gl国家代码设置搜索国家
hl语言代码设置接口语言
num10-100岁每页结果
filter0 个禁用重复过滤
nfpr页:1禁用自动更正

分发的时间安排

对于大规模的SRERP监测,要跨时间分发请求,以避免爆发模式. 与其在1小时内刮掉1万个关键字,不如用自然交通曲线将关键字分布在8-12小时之间(在营业时间请求更多,夜间请求更少).

目的不仅仅是要避开块块——它是为了让你的刮行流量与正常的用户搜索行为无法区分. 每一个细节都很重要。

更多关于建设可靠,大规模废气管道的情况,见我们 完整网络擦除代理指南代理用户网络刮切解决方案。 。 。

准备开始了吗?

通过AI过滤访问148多个国家的5000多万个住宅IP。

查看价格住宅代理
← 返回博客