SeleniumとPuppeteerの検出回避の完全ガイド
現代のアンチボットシステムは、JavaScriptの変数からWebDriverの動作の特徴まで、数十の兆候を使って自動化されたブラウザを簡単に認識します。サイトはCloudflare、DataDome、PerimeterX、そして独自のソリューションを使用して、標準構成のSeleniumとPuppeteerからのリクエストの90%をブロックします。
このガイドでは、基本的な設定から高度な検出回避技術まで、すべての自動化マスキング手法を説明します。ほとんどの保護システムに対して機能するPythonとNode.jsのコード例を含む完成したソリューションを提供します。
サイトが自動化を検出する方法
アンチボットシステムは、同時に多数のパラメータを分析してブラウザを評価します。たとえ1つの兆候を隠しても、他の兆候が自動化を明らかにします。すべての検出手法を理解することが、効果的なマスキングの鍵です。
WebDriverインジケーター
最も簡単な検出方法は、自動化されたブラウザにのみ存在するJavaScript変数をチェックすることです:
// これらの変数はSelenium/Puppeteerを示します
navigator.webdriver === true
window.navigator.webdriver === true
document.$cdc_ // ChromeDriver特有の変数
window.document.documentElement.getAttribute("webdriver")
navigator.plugins.length === 0 // 自動化されたブラウザにはプラグインがありません
navigator.languages === "" // 言語リストが空です
Cloudflareや同様のシステムは、まずこれらのプロパティをチェックします。1つでもポジティブな結果が返されると、リクエストはブロックされます。
ブラウザフィンガープリンティング
高度なシステムは、数十のパラメータに基づいてブラウザのユニークなフィンガープリントを作成します:
- Canvasフィンガープリンティング — 隠れた画像のレンダリングとピクセルデータの分析
- WebGLフィンガープリンティング — グラフィックレンダラーとGPUのパラメータ
- Audio Context — オーディオ処理のユニークな特性
- フォントフィンガープリンティング — システムにインストールされているフォントのリスト
- 画面解像度 — 画面の解像度、色深度、利用可能な領域
- タイムゾーンと言語 — タイムゾーン、ブラウザの言語、システムのロケール
自動化されたブラウザは、これらのパラメータの典型的でない組み合わせを持つことがよくあります。たとえば、ヘッドレスChromeはプラグインを持たず、WebGLをサポートしています — このような組み合わせは実際のユーザーには非常に稀です。
行動分析
現代のシステムは行動パターンを追跡します:
- マウスの動き — ボットはカーソルを直線的に動かすか、全く動かさない
- 行動の速度 — フォームの即時入力、人間とは思えないクリック速度
- スクロールパターン — スムーズなスクロールではなく、急激なジャンプ
- キーボードイベント — 押下間の自然な遅延がない
- リクエストの頻度 — 行動間の間隔があまりにも規則的
重要: DataDomeとPerimeterXは、行動分析のために機械学習を使用しています。彼らは数百万のセッションで訓練されており、技術的なパラメータが正しくマスキングされていても、行動が不自然に見えるとボットを認識できます。
Seleniumの基本的なマスキング
標準構成のSelenium WebDriverは、多くの痕跡を残します。PythonとChromeDriverの例を用いて、検出を最小限に抑えるためのステップバイステップの設定を見ていきましょう。
WebDriverフラグの無効化
最初のステップは、navigator.webdriver変数を隠すことです。これはChrome DevTools Protocolを通じて行います:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
# Chromeオプションの設定
chrome_options = Options()
# 自動化フラグを無効化
chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
chrome_options.add_experimental_option('useAutomationExtension', False)
# ドライバーを作成
driver = webdriver.Chrome(options=chrome_options)
# CDPを通じてwebdriverを削除
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
'source': '''
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
'''
})
driver.get('https://example.com')
User-Agentやその他のヘッダーの設定
ヘッドレスブラウザは、古いまたは特定のUser-Agent文字列を使用することがよくあります。実際のブラウザの最新のUser-Agentを設定する必要があります:
# Windows上の最新のUser-Agent Chrome
user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
chrome_options.add_argument(f'user-agent={user_agent}')
# マスキングのための追加の引数
chrome_options.add_argument('--disable-blink-features=AutomationControlled')
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-gpu')
# 実際のユーザーと同じウィンドウサイズ
chrome_options.add_argument('--window-size=1920,1080')
chrome_options.add_argument('--start-maximized')
プラグインと言語の追加
自動化されたブラウザにはプラグインがなく、言語リストが空であることがよくあります。これをCDPを通じて修正します:
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
'source': '''
Object.defineProperty(navigator, 'languages', {
get: () => ['en-US', 'en', 'ru']
});
Object.defineProperty(navigator, 'plugins', {
get: () => [
{
0: {type: "application/x-google-chrome-pdf", suffixes: "pdf", description: "Portable Document Format"},
description: "Portable Document Format",
filename: "internal-pdf-viewer",
length: 1,
name: "Chrome PDF Plugin"
},
{
0: {type: "application/pdf", suffixes: "pdf", description: ""},
description: "",
filename: "mhjfbmdgcfjbbpaeojofohoefgiehjai",
length: 1,
name: "Chrome PDF Viewer"
}
]
});
Object.defineProperty(navigator, 'platform', {
get: () => 'Win32'
});
'''
})
Seleniumの完全な設定例
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import random
def create_stealth_driver():
chrome_options = Options()
# マスキングの基本設定
chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
chrome_options.add_experimental_option('useAutomationExtension', False)
chrome_options.add_argument('--disable-blink-features=AutomationControlled')
# User-Agent
user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
chrome_options.add_argument(f'user-agent={user_agent}')
# ウィンドウサイズ
chrome_options.add_argument('--window-size=1920,1080')
chrome_options.add_argument('--start-maximized')
driver = webdriver.Chrome(options=chrome_options)
# CDPを通じたマスキングスクリプト
stealth_script = '''
Object.defineProperty(navigator, 'webdriver', {get: () => undefined});
Object.defineProperty(navigator, 'languages', {get: () => ['en-US', 'en']});
Object.defineProperty(navigator, 'platform', {get: () => 'Win32'});
window.chrome = {
runtime: {}
};
Object.defineProperty(navigator, 'plugins', {
get: () => [1, 2, 3, 4, 5]
});
'''
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
'source': stealth_script
})
return driver
# 使用例
driver = create_stealth_driver()
driver.get('https://bot.sannysoft.com/') # 検出テスト用サイト
検出回避のためのPuppeteerの設定
PuppeteerはSeleniumと同様の検出問題を抱えています。しかし、Node.js用には、ほとんどのマスキング設定を自動化するpuppeteer-extra-plugin-stealthというライブラリがあります。
puppeteer-extraのインストール
npm install puppeteer puppeteer-extra puppeteer-extra-plugin-stealth
stealthプラグインを使った基本設定
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
// マスキングプラグインを使用
puppeteer.use(StealthPlugin());
(async () => {
const browser = await puppeteer.launch({
headless: 'new', // 新しいヘッドレスモードのChrome
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-accelerated-2d-canvas',
'--disable-gpu',
'--window-size=1920,1080',
'--disable-web-security',
'--disable-features=IsolateOrigins,site-per-process'
]
});
const page = await browser.newPage();
// ビューポートの設定
await page.setViewport({
width: 1920,
height: 1080,
deviceScaleFactor: 1
});
// User-Agentの設定
await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36');
// 追加のヘッダー
await page.setExtraHTTPHeaders({
'Accept-Language': 'en-US,en;q=0.9',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
});
await page.goto('https://bot.sannysoft.com/');
// 検出テスト用のスクリーンショット
await page.screenshot({ path: 'test.png' });
await browser.close();
})();
プラグインなしでの手動設定
完全な制御が必要な場合やサードパーティのライブラリを使用できない場合は、手動でマスキングを設定します:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const page = await browser.newPage();
// webdriverやその他のプロパティをオーバーライド
await page.evaluateOnNewDocument(() => {
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
});
Object.defineProperty(navigator, 'languages', {
get: () => ['en-US', 'en']
});
Object.defineProperty(navigator, 'plugins', {
get: () => [1, 2, 3, 4, 5]
});
// Chromeヘッドレスをマスキング
Object.defineProperty(navigator, 'platform', {
get: () => 'Win32'
});
window.chrome = {
runtime: {}
};
// permissionsをオーバーライド
const originalQuery = window.navigator.permissions.query;
window.navigator.permissions.query = (parameters) => (
parameters.name === 'notifications' ?
Promise.resolve({ state: Notification.permission }) :
originalQuery(parameters)
);
});
await page.goto('https://example.com');
await browser.close();
})();
Cloudflare回避のための設定
Cloudflareは高度な検出方法を使用しています。回避するためには、ランダムな遅延と行動のエミュレーションを追加する必要があります:
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());
async function bypassCloudflare(url) {
const browser = await puppeteer.launch({
headless: 'new',
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-web-security'
]
});
const page = await browser.newPage();
// ランダムなUser-Agent
const userAgents = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
];
await page.setUserAgent(userAgents[Math.floor(Math.random() * userAgents.length)]);
// ページに移動
await page.goto(url, { waitUntil: 'networkidle2' });
// Cloudflareのチェックを待つ(通常5〜10秒)
await page.waitForTimeout(8000);
// ランダムなマウスの動き
await page.mouse.move(100, 100);
await page.mouse.move(200, 200);
const content = await page.content();
await browser.close();
return content;
}
JavaScriptフィンガープリンティングへの対策
JavaScriptフィンガープリンティングは、多数のパラメータに基づいてブラウザのユニークなフィンガープリントを作成することです。webdriverを隠しても、システムは自動化を検出するために他の数百のプロパティを分析します。
フィンガープリンティングの主要なベクトル
アンチボットシステムは以下のパラメータをチェックします:
| パラメータ | チェックされる内容 | 検出リスク |
|---|---|---|
| navigator.webdriver | 自動化フラグの存在 | クリティカル |
| navigator.plugins | プラグインの数と種類 | 高い |
| window.chrome | Chrome APIの存在 | 中程度 |
| navigator.permissions | ブラウザの権限API | 中程度 |
| screen.colorDepth | 画面の色深度 | 低い |
| navigator.hardwareConcurrency | CPUのコア数 | 低い |
複合的なマスキングスクリプト
以下のスクリプトは、問題のあるプロパティのほとんどをオーバーライドします。これをCDP(Selenium)またはevaluateOnNewDocument(Puppeteer)を通じて埋め込んでください:
const stealthScript = `
// webdriverを削除
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
});
// chromeオブジェクトを追加
window.chrome = {
runtime: {},
loadTimes: function() {},
csi: function() {},
app: {}
};
// permissionsをオーバーライド
const originalQuery = window.navigator.permissions.query;
window.navigator.permissions.query = (parameters) => (
parameters.name === 'notifications' ?
Promise.resolve({ state: Notification.permission }) :
originalQuery(parameters)
);
// プラグインをマスキング
Object.defineProperty(navigator, 'plugins', {
get: () => {
return [
{
0: {type: "application/x-google-chrome-pdf", suffixes: "pdf"},
description: "Portable Document Format",
filename: "internal-pdf-viewer",
length: 1,
name: "Chrome PDF Plugin"
},
{
0: {type: "application/pdf", suffixes: "pdf"},
description: "Portable Document Format",
filename: "internal-pdf-viewer",
length: 1,
name: "Chrome PDF Viewer"
},
{
0: {type: "application/x-nacl"},
description: "Native Client Executable",
filename: "internal-nacl-plugin",
length: 2,
name: "Native Client"
}
];
}
});
// 言語
Object.defineProperty(navigator, 'languages', {
get: () => ['en-US', 'en']
});
// プラットフォーム
Object.defineProperty(navigator, 'platform', {
get: () => 'Win32'
});
// ベンダー
Object.defineProperty(navigator, 'vendor', {
get: () => 'Google Inc.'
});
// Seleniumの痕跡を削除
delete window.cdc_adoQpoasnfa76pfcZLmcfl_Array;
delete window.cdc_adoQpoasnfa76pfcZLmcfl_Promise;
delete window.cdc_adoQpoasnfa76pfcZLmcfl_Symbol;
// Battery API(ヘッドレスでは存在しない)
if (!navigator.getBattery) {
navigator.getBattery = () => Promise.resolve({
charging: true,
chargingTime: 0,
dischargingTime: Infinity,
level: 1
});
}
`;
WebDriverプロパティの削除
ChromeDriverや他のWebDriver実装は、グローバルスコープに特有の変数を追加します。これらの変数はcdc_プレフィックスで始まり、保護システムによって簡単に検出されます。
cdc変数の検出
これらの変数の存在を確認するには、簡単なスクリプトを使用します:
// すべてのcdc変数を検索
for (let key in window) {
if (key.includes('cdc_')) {
console.log('WebDriver変数が検出されました:', key);
}
}
// 一般的なChromeDriver変数:
// cdc_adoQpoasnfa76pfcZLmcfl_Array
// cdc_adoQpoasnfa76pfcZLmcfl_Promise
// cdc_adoQpoasnfa76pfcZLmcfl_Symbol
// $cdc_asdjflasutopfhvcZLmcfl_
方法1:CDPを通じて削除
最も信頼性の高い方法は、ページが読み込まれる前にChrome DevTools Protocolを通じて変数を削除することです:
from selenium import webdriver
driver = webdriver.Chrome()
# すべてのcdc変数を削除
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
'source': '''
// 既知のcdc変数を削除
const cdcProps = [
'cdc_adoQpoasnfa76pfcZLmcfl_Array',
'cdc_adoQpoasnfa76pfcZLmcfl_Promise',
'cdc_adoQpoasnfa76pfcZLmcfl_Symbol',
'$cdc_asdjflasutopfhvcZLmcfl_'
];
cdcProps.forEach(prop => {
delete window[prop];
});
// 'cdc_'を含むすべての変数を削除
Object.keys(window).forEach(key => {
if (key.includes('cdc_') || key.includes('$cdc_')) {
delete window[key];
}
});
'''
})
方法2:ChromeDriverの修正
より過激なアプローチは、ChromeDriverのバイナリファイルを変更し、cdc_の文字列を別の文字列に置き換えることです。これにより、これらの変数の作成を防ぎます:
import re
def patch_chromedriver(driver_path):
"""
ChromeDriverをパッチし、'cdc_'をランダムな文字列に置き換えます
"""
with open(driver_path, 'rb') as f:
content = f.read()
# 'cdc_'のすべての出現を'dog_'(または同じ長さの任意の文字列)に置き換えます
patched = content.replace(b'cdc_', b'dog_')
with open(driver_path, 'wb') as f:
f.write(patched)
print(f'ChromeDriverがパッチされました: {driver_path}')
# 使用例
patch_chromedriver('/path/to/chromedriver')
注意: ChromeDriverのバイナリファイルの修正は、動作を妨げる可能性があります。パッチを当てる前に必ずバックアップを取ってください。この方法はすべてのChromeDriverのバージョンで機能するわけではありません。
方法3:undetected-chromedriverの使用
undetected-chromedriverライブラリは、起動時にChromeDriverを自動的にパッチします:
pip install undetected-chromedriver
import undetected_chromedriver as uc
# 自動パッチ付きのドライバーを作成
driver = uc.Chrome()
driver.get('https://nowsecure.nl/') # 検出テスト用サイト
input('Enterを押して閉じます...')
driver.quit()
Canvas、WebGL、Audio APIのマスキング
Canvas、WebGL、Audioフィンガープリンティングは、グラフィックレンダリングや音声処理の特徴に基づいてユニークなフィンガープリントを作成する方法です。ブラウザ、OS、ハードウェアの組み合わせは、ユニークな結果をもたらします。
Canvasフィンガープリンティング
システムはCanvasに隠れた画像を描画し、得られたピクセルを分析します。ヘッドレスブラウザは、GPUアクセラレーションがないため、典型的でない結果を出すことがよくあります。
// 典型的なCanvasフィンガープリンティングコード
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.textBaseline = 'top';
ctx.font = '14px Arial';
ctx.fillText('Browser fingerprint', 2, 2);
const fingerprint = canvas.toDataURL();
保護のために、Canvas APIにランダムなノイズを追加することができます:
const canvasNoiseScript = `
// Canvasにランダムなノイズを追加
const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
const originalToBlob = HTMLCanvasElement.prototype.toBlob;
const originalGetImageData = CanvasRenderingContext2D.prototype.getImageData;
// ノイズを追加する関数
const addNoise = (canvas, context) => {
const imageData = originalGetImageData.call(context, 0, 0, canvas.width, canvas.height);
for (let i = 0; i < imageData.data.length; i += 4) {
// RGBに最小限のノイズを追加(目に見えない)
imageData.data[i] += Math.floor(Math.random() * 3) - 1;
imageData.data[i + 1] += Math.floor(Math.random() * 3) - 1;
imageData.data[i + 2] += Math.floor(Math.random() * 3) - 1;
}
context.putImageData(imageData, 0, 0);
};
// toDataURLをオーバーライド
HTMLCanvasElement.prototype.toDataURL = function() {
if (this.width > 0 && this.height > 0) {
const context = this.getContext('2d');
addNoise(this, context);
}
return originalToDataURL.apply(this, arguments);
};
`;
WebGLフィンガープリンティング
WebGLは、GPUやドライバーに関する情報を提供します。ヘッドレスブラウザは、実際のGPUの代わりにSwiftShader(ソフトウェアレンダラー)を表示することがよくあります:
const webglMaskScript = `
// WebGLパラメータをマスキング
const getParameter = WebGLRenderingContext.prototype.getParameter;
WebGLRenderingContext.prototype.getParameter = function(parameter) {
// UNMASKED_VENDOR_WEBGL
if (parameter === 37445) {
return 'Intel Inc.';
}
// UNMASKED_RENDERER_WEBGL
if (parameter === 37446) {
return 'Intel Iris OpenGL Engine';
}
return getParameter.call(this, parameter);
};
// WebGL2用にも
if (typeof WebGL2RenderingContext !== 'undefined') {
const getParameter2 = WebGL2RenderingContext.prototype.getParameter;
WebGL2RenderingContext.prototype.getParameter = function(parameter) {
if (parameter === 37445) {
return 'Intel Inc.';
}
if (parameter === 37446) {
return 'Intel Iris OpenGL Engine';
}
return getParameter2.call(this, parameter);
};
}
`;
Audio Contextフィンガープリンティング
Audio APIもユニークなフィンガープリントを提供します。オーディオ処理にノイズを追加します:
const audioMaskScript = `
// Audio Contextにノイズを追加
const AudioContext = window.AudioContext || window.webkitAudioContext;
if (AudioContext) {
const originalCreateAnalyser = AudioContext.prototype.createAnalyser;
AudioContext.prototype.createAnalyser = function() {
const analyser = originalCreateAnalyser.call(this);
const originalGetFloatFrequencyData = analyser.getFloatFrequencyData;
analyser.getFloatFrequencyData = function(array) {
originalGetFloatFrequencyData.call(this, array);
// 最小限のノイズを追加
for (let i = 0; i < array.length; i++) {
array[i] += Math.random() * 0.0001;
}
};
return analyser;
};
}
`;
人間の行動の模倣
完璧な技術的マスキングがあっても、ボットは行動によって自らを明らかにします。機械学習システムは、マウスの動き、行動の速度、イベントの順序を分析します。
行動間のランダムな遅延
固定の遅延を使用しないでください。実際のユーザーはさまざまな長さの間隔を置きます:
import random
import time
def human_delay(min_seconds=1, max_seconds=3):
"""人間を模倣したランダムな遅延"""
delay = random.uniform(min_seconds, max_seconds)
time.sleep(delay)
# 使用例
driver.get('https://example.com')
human_delay(2, 4) # 2〜4秒の遅延
element = driver.find_element(By.ID, 'search')
human_delay(0.5, 1.5) # 入力前の短い遅延
element.send_keys('search query')
human_delay(1, 2)
スムーズなマウスの動き
ボットはマウスを直線的に動かしたり、カーソルをテレポートさせたりします。実際のユーザーは加速と減速を伴う曲線的な軌道を作ります:
// Puppeteer: スムーズなマウスの動き
async function humanMouseMove(page, targetX, targetY) {
const steps = 25; // 中間ポイントの数
const currentPos = await page.evaluate(() => ({
x: window.mouseX || 0,
y: window.mouseY || 0
}));
for (let i = 0; i <= steps; i++) {
const t = i / steps;
// スムーズさのためにイージングを使用
const ease = t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
const x = currentPos.x + (targetX - currentPos.x) * ease;
const y = currentPos.y + (targetY - currentPos.y) * ease;
await page.mouse.move(x, y);
await page.waitForTimeout(Math.random() * 10 + 5);
}
// 位置を保存
await page.evaluate((x, y) => {
window.mouseX = x;
window.mouseY = y;
}, targetX, targetY);
}
// 使用例
await humanMouseMove(page, 500, 300);
await page.mouse.click(500, 300);
自然なスクロール
実際のユーザーは、コンテンツを読むために停止しながらスムーズにスクロールします:
async function humanScroll(page) {
const scrollHeight = await page.evaluate(() => document.body.scrollHeight);
const viewportHeight = await page.evaluate(() => window.innerHeight);
let currentPosition = 0;
while (currentPosition < scrollHeight - viewportHeight) {
// ランダムなスクロールステップ(200〜500px)
const scrollStep = Math.floor(Math.random() * 300) + 200;
currentPosition += scrollStep;
// スムーズなスクロール
await page.evaluate((pos) => {
window.scrollTo({
top: pos,
behavior: 'smooth'
});
}, currentPosition);
// コンテンツを「読む」ための遅延(1〜3秒)
await page.waitForTimeout(Math.random() * 2000 + 1000);
}
}
// 使用例
await page.goto('https://example.com');
await humanScroll(page);
自然なテキスト入力
人々は異なる速度で入力し、誤字をし、それを修正します:
async function humanTypeText(page, selector, text) {
await page.click(selector);
for (let char of text) {
// 押下間のランダムな遅延(50〜200ms)
const delay = Math.random() * 150 + 50;
await page.waitForTimeout(delay);
// 5%の確率で誤字
if (Math.random() < 0.05) {
// ランダムな文字を入力
const wrongChar = String.fromCharCode(97 + Math.floor(Math.random() * 26));
await page.keyboard.type(wrongChar);
await page.waitForTimeout(100 + Math.random() * 100);
// 削除(Backspace)
await page.keyboard.press('Backspace');
await page.waitForTimeout(50 + Math.random() * 50);
}
await page.keyboard.type(char);
}
}
// 使用例
await humanTypeText(page, '#search-input', 'example search query');
完全な匿名性のためのプロキシ統合
ブラウザのマスキングは、すべてのリクエストが同じIPアドレスから来る場合は無意味です。アンチボットシステムは、各IPからのリクエストの数を追跡し、疑わしい活動をブロックします。プロキシは、あらゆる真剣な自動化の必須要素です。
プロキシの種類の選択
異なるタスクには異なる種類のプロキシが必要です:
| プロキシの種類 | 利点 | 用途 |
|---|---|---|
| プロキシタイプ1 | 利点1 | 用途1 |
| プロキシタイプ2 | 利点2 | 用途2 |
| プロキシタイプ3 | 利点3 | 用途3 |