GoogleがSERPスクレーパーを検出する方法
Googleは、自動アクセスから検索結果を保護することに大きく投資しています。 ブロックを避ける前に、Googleが使用する検出方法を理解する必要があります。 各メソッドは異なる信号をターゲットにし、効果的なSERPスクレイピングは、それらすべてを同時に対処する必要があります。
SERPスクレイピングアーキテクチャの完全概要については、当社のを参照してください。 プロキシガイドによるSERPスクレイピング. .
IPベースの検出
防衛の最初の行はIP解析です。 Google は IP アドレスごとの問い合わせの容積を追跡し、正常な人間の調査パターンを超過するそれらにフラグを付けます。 特定の信号は下記のものを含んでいます:
- 要求頻度: 単一のIPから1分あたりの検索数が少ないほど、制限速度がトリガーされます。
- IPの評判: 既知のデータセンター IP 範囲は、即時スカルチニーを受け取る
- 地理的な矛盾: ドイツから英語のUS-targetedクエリを作るIPは、フラグを上げます
- ASN分析: Google は、ホスティングプロバイダと ISP に属する IP ブロックを識別します。
ブラウザの指紋
IPアドレスを超えて、Googleは、自動化の兆候のために要求自体を調べます。
| シグナル | Googleのチェック | レッドフラッグ |
|---|---|---|
| ユーザーエージェント | ブラウザとOSの識別文字列 | 他のヘッダで欠損、または矛盾する |
| ヘッダーの受け入れ | コンテンツの種類 好み | 受け入れ言語または非標準 受け入れ値の欠如 |
| TLS指紋 | SSL/TLS ハンドシェイク特性 | 指紋マッチング既知のHTTPライブラリ(requests、urllib) |
| JavaScriptの実行 | クライアント側スクリプトの動作 | JavaScript の実行なし (ヘッドレス検出) |
| クッキーの動作 | クッキーの受け入れと管理 | クッキーや同一のクッキーのパターンを要求しない |
これらの技術を深く見て、記事を読んでください アンチボットシステムがプロキシを検出する方法. .
行動分析
Google は、リクエスト全体でパターンを分析し、自動化を検出します。
- リクエストのタイミング: 要求(例えば、正確に3秒間隔)間の完全に一貫した間隔は不自然です
- クエリパターン: キーワードをアルファベット順にスクレイピングしたり、予測可能なシーケンスが自動化される
- セッションの動作: 実際のユーザーは複数のページをブラウズし、結果をクリックし、時間の読書を費やします。 — スクレーパーはSERPを獲得します
- ボリュームパターン: 関連するIPからクエリのボリュームのSuddenスパイクは、調整されたスクレイピングを提案します
アンチブロック戦略の3層
Googleブロックを回避するには、レイヤーされたアプローチが必要です。 ひとつひとつの技法は、自分では十分ではありません。
レイヤー1:プロキシインフラストラクチャ
あなたのプロキシの選択はあなたのアンチブロック戦略の基礎です。 ProxyHat住宅プロキシ 持続可能なSERPスクレイピングに必要なIPダイバーシティと信頼レベルを提供します。
層 2: 要求構成
すべてのHTTPは、実際のブラウザから来るように要求しなければなりません。 ヘッダー、クッキー、タイミングはすべて現実的である必要があります。
層3:行動パターン
スクレイピング活動の全体的なパターンは、自然検索行動を模倣する必要があります。 これは、ランダム化された遅延、さまざまなクエリシーケンス、および適切なリクエストボリュームを意味します。
住宅のプロキシ:あなたの最初の防衛
データセンタから作ることができる最もインパクトのある単一の変更は、 住宅のプロキシ. ここでは、住宅IPは、Googleの観点から根本的に異なる理由です。
- 住宅用IPは、実際のISP(コンキャスト、AT&T、BT、Deutsche Telekom)に属し、クラウドプロバイダではありません
- Googleは、正当なユーザーをブロックすることなく、住宅IP範囲をブロックすることはできません
- 各IPは、その実際のユーザーによって構築された閲覧履歴と評判を持っています
- 住宅用IPは、位置精度SERPsの都市レベルのジオターゲティングをサポート
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,
)参照して下さい ProxyHat ドキュメント 高度の回転およびセッション設定のため。
現実的な要求ヘッダー
不完全なヘッダーまたは矛盾しないヘッダーは、スクレーパーがブロックされる最も一般的な理由の1つです。 ここでは、完全で現実的なヘッダーセットです。
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常にユーザーエージェントの文字列を現在のブラウザのバージョンで更新します。 クロム90ユーザーエージェントを2026で送信すると、すぐに赤いフラグになります。
レート制限と要求のタイミング
リクエストのパターンは、リクエストそのものと同じくらい重要です。 ここに証明されたタイミングの作戦があります:
ランダム遅延
リクエスト間の固定間隔を使用しないでください。 代わりに、人間の検索行動を模倣する遅延をランダム化します。
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)ボリュームガイドラインのリクエスト
| プロキシタイプ | IPごとの安全な要求/分 | 最高の同時IPs |
|---|---|---|
| 住宅(回転) | 1-2日 | 無制限(プールは回転します) |
| 住宅(粘着セッション) | 1 / 30秒 | プールのサイズに基づく |
| データセンター | 1 / 60秒 | 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地理的一貫性
1つの微妙で重要な反検出の測定はあなたの要求変数を渡る地理的な一貫性を保障します:
- プロキシIPが米国にいる場合、設定
gl=usそして、hl=en - Accept-Language ヘッダーを対象の locale にマッチする
- その国で共通するOS/ブラウザコンビネーション用のUser-Agent文字列を使用する
- タイムゾーンの適切なリクエスト時間を設定する
プロキシハートの ジオターゲティング機能 特定の国や都市からプロキシを選択し、この一貫性を維持するためにそれを簡単にします。 ガイドのロケーションターゲットリクエストの使用について詳しく知る ブロックせずにスクレイピング. .
Node.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)Google検索パラメータ
これらのパラメータを使用して、非パーソナライズされた結果をきれいにします。
| パラメータ | バリュー | ミッション |
|---|---|---|
pws | 0 の 0 | パーソナライズされた結果を無効にする |
gl | 国コード | 検索国を設定 |
hl | 言語コード | インターフェイス言語の設定 |
num | 10-100円 | ページごとの結果 |
filter | 0 の 0 | 重複フィルタを無効にする |
nfpr | 1 | 無効な自動補正 |
分散型スケジューリング
大規模なSERP監視では、破裂パターンを回避するために、リクエストを時間通りに配信します。 1時間に10,000キーワードをスクレイピングする代わりに、自然交通の曲線(営業時間のより多くの要求、夜間に少ない)で8〜12時間にわたってそれらを広げます。
目標はブロックを回避するだけでなく、通常のユーザー検索の動作からトラフィックを乱用させることです。 お問い合わせ
信頼性の高い大規模なスクレイピングパイプラインを構築するには、 ウェブスクレイピングプロキシの完全なガイド そして、 ProxyHat Webスクレイピングソリューション. .






