대량 요청 시 차단 방지: 기술 및 도구
계정 및 IP 차단은 파싱, 자동화 및 소셜 미디어에서의 대량 작업 시 주요 문제입니다. 현대의 안티봇 시스템은 요청 빈도부터 브라우저 지문까지 수십 가지 매개변수를 분석합니다. 이 가이드에서는 자동화 탐지의 구체적인 메커니즘과 이를 우회하는 실용적인 방법을 살펴보겠습니다.
자동화 탐지 메커니즘
현대의 보호 시스템은 봇을 식별하기 위해 다단계 분석을 사용합니다. 이러한 메커니즘을 이해하는 것은 올바른 우회 전략을 선택하는 데 매우 중요합니다.
분석의 주요 매개변수
IP 평판: 안티봇 시스템은 IP 주소의 이력, 데이터 센터 소속, 블랙리스트 여부를 확인합니다. 알려진 프록시 풀에서의 IP는 더 자주 차단됩니다.
요청 빈도(Request Rate): 사람은 물리적으로 1분에 100개의 요청을 보낼 수 없습니다. 시스템은 총 요청 수뿐만 아니라 시간에 따른 분포도 분석합니다. 요청 간 균일한 간격은 봇을 드러냅니다.
행동 패턴: 행동의 순서, 스크롤 깊이, 마우스 움직임, 페이지에서의 시간. 지연 없이 즉시 링크를 클릭하는 봇은 쉽게 인식됩니다.
기술적 지문: User-Agent, HTTP 헤더, 헤더의 순서, TLS 지문, Canvas/WebGL 지문. 이러한 매개변수의 불일치는 안티봇 시스템에 대한 경고 신호입니다.
| 매개변수 | 분석되는 내용 | 탐지 위험 |
|---|---|---|
| IP 주소 | 평판, ASN, 지리적 위치 | 높음 |
| User-Agent | 브라우저 버전, OS, 장치 | 중간 |
| TLS 지문 | 암호 집합, 확장 | 높음 |
| HTTP/2 지문 | 헤더 순서, 설정 | 높음 |
| Canvas/WebGL | 그래픽 렌더링 | 중간 |
| 행동 | 클릭, 스크롤, 시간 | 높음 |
요청 속도 제한 및 요청 빈도 제어
요청 전송 속도 제어는 차단 방지의 첫 번째 방어선입니다. 프록시 회전이 있더라도 너무 공격적인 파싱은 차단으로 이어질 수 있습니다.
동적 지연
고정 간격(예: 요청 간 정확히 2초)은 쉽게 인식됩니다. 정규 분포를 사용하여 무작위 지연을 적용하세요:
import time
import random
import numpy as np
def human_delay(min_delay=1.5, max_delay=4.0, mean=2.5, std=0.8):
"""
인간 행동을 모방하는 정규 분포의 지연 생성
"""
delay = np.random.normal(mean, std)
# 범위 제한
delay = max(min_delay, min(delay, max_delay))
# 현실성을 위해 마이크로 지연 추가
delay += random.uniform(0, 0.3)
time.sleep(delay)
# 사용 예
for url in urls:
response = session.get(url)
human_delay(min_delay=2, max_delay=5, mean=3, std=1)
적응형 요청 속도 제한
보다 발전된 접근 방식은 서버의 응답을 기반으로 속도를 조정하는 것입니다. 429(요청이 너무 많음) 또는 503 코드를 받으면 자동으로 속도를 줄이세요:
class AdaptiveRateLimiter:
def __init__(self, initial_delay=2.0):
self.current_delay = initial_delay
self.min_delay = 1.0
self.max_delay = 30.0
self.error_count = 0
def wait(self):
time.sleep(self.current_delay + random.uniform(0, 0.5))
def on_success(self):
# 성공적인 요청 시 점진적으로 속도를 높입니다
self.current_delay = max(
self.min_delay,
self.current_delay * 0.95
)
self.error_count = 0
def on_rate_limit(self):
# 차단 시 급격히 속도를 줄입니다
self.error_count += 1
self.current_delay = min(
self.max_delay,
self.current_delay * (1.5 + self.error_count * 0.5)
)
print(f"요청 속도 제한에 도달했습니다. 새로운 지연: {self.current_delay:.2f}s")
# 사용 예
limiter = AdaptiveRateLimiter(initial_delay=2.0)
for url in urls:
limiter.wait()
response = session.get(url)
if response.status_code == 429:
limiter.on_rate_limit()
time.sleep(60) # 재시도 전 대기
elif response.status_code == 200:
limiter.on_success()
else:
# 기타 오류 처리
pass
실용적인 조언: 다양한 사이트에 따라 최적의 속도는 다릅니다. 대형 플랫폼(구글, 페이스북)은 하나의 IP에서 분당 5-10개의 요청을 허용합니다. 소규모 사이트는 시간당 20-30개의 요청으로도 차단할 수 있습니다. 항상 보수적으로 시작하고 점진적으로 부하를 증가시키며 오류 비율을 추적하세요.
프록시 회전 및 IP 주소 관리
대량 요청에 하나의 IP 주소를 사용하면 차단이 보장됩니다. 프록시 회전은 부하를 분산시키고 탐지 위험을 줄입니다.
회전 전략
1. 요청 기반 회전: 각 요청 후 또는 N 요청마다 IP를 변경합니다. 각 요청의 익명성이 중요한 검색 엔진 파싱에 적합합니다.
2. 시간 기반 회전: 5-15분마다 IP를 변경합니다. 세션의 안정성이 중요한 소셜 미디어 작업에 효과적입니다.
3. 스티키 세션: 전체 사용자 세션(인증, 행동 순서)에 하나의 IP를 사용합니다. CSRF 보호가 있는 사이트에 중요합니다.
import requests
from itertools import cycle
class ProxyRotator:
def __init__(self, proxy_list, rotation_type='request', rotation_interval=10):
"""
rotation_type: 'request' (각 요청) 또는 'time' (시간 기준)
rotation_interval: 요청 수 또는 초
"""
self.proxies = cycle(proxy_list)
self.current_proxy = next(self.proxies)
self.rotation_type = rotation_type
self.rotation_interval = rotation_interval
self.request_count = 0
self.last_rotation = time.time()
def get_proxy(self):
if self.rotation_type == 'request':
self.request_count += 1
if self.request_count >= self.rotation_interval:
self.current_proxy = next(self.proxies)
self.request_count = 0
print(f"회전됨: {self.current_proxy}")
elif self.rotation_type == 'time':
if time.time() - self.last_rotation >= self.rotation_interval:
self.current_proxy = next(self.proxies)
self.last_rotation = time.time()
print(f"회전됨: {self.current_proxy}")
return {'http': self.current_proxy, 'https': self.current_proxy}
# 사용 예
proxy_list = [
'http://user:pass@proxy1.example.com:8000',
'http://user:pass@proxy2.example.com:8000',
'http://user:pass@proxy3.example.com:8000',
]
rotator = ProxyRotator(proxy_list, rotation_type='request', rotation_interval=5)
for url in urls:
proxies = rotator.get_proxy()
response = requests.get(url, proxies=proxies, timeout=10)
프록시 유형 선택
| 프록시 유형 | 신뢰 수준 | 속도 | 용도 |
|---|---|---|---|
| 데이터 센터 | 낮음 | 높음 | 간단한 파싱, API |
| 주거용 | 높음 | 중간 | 소셜 미디어, 보호된 사이트 |
| 모바일 | 매우 높음 | 중간 | 인스타그램, 틱톡, 안티 프로드 |
소셜 미디어 및 강력한 보호가 있는 플랫폼에서 대량 작업을 수행할 때는 주거용 프록시를 사용하세요. 이들은 일반 가정용 연결처럼 보이며 블랙리스트에 오르는 일이 드뭅니다. 데이터 센터는 속도가 중요한 덜 보호된 리소스에 적합합니다.
브라우저 지문 인식 및 TLS 지문
IP 회전이 있더라도 기술적 브라우저 지문 및 TLS 연결로 인해 추적될 수 있습니다. 이러한 매개변수는 각 클라이언트에 대해 고유하며 위조하기 어렵습니다.
TLS 지문 인식
HTTPS 연결을 설정할 때 클라이언트는 지원하는 암호 및 확장의 조합을 포함한 ClientHello를 보냅니다. 이 조합은 각 라이브러리에 대해 고유합니다. 예를 들어, Python requests는 OpenSSL을 사용하며, 이 지문은 Chrome과 쉽게 구별됩니다.
문제: 표준 라이브러리(requests, urllib, curl)는 실제 브라우저와 다른 지문을 가지고 있습니다. Cloudflare, Akamai, DataDome과 같은 서비스는 봇 차단을 위해 TLS 지문 인식을 적극적으로 사용합니다.
해결책: 브라우저의 TLS 지문을 모방하는 라이브러리를 사용하세요. Python의 경우 curl_cffi, tls_client 또는 playwright/puppeteer를 사용하여 브라우저를 완전히 에뮬레이트할 수 있습니다.
# 설치: pip install curl-cffi
from curl_cffi import requests
# Chrome 110 모방
response = requests.get(
'https://example.com',
impersonate="chrome110",
proxies={'https': 'http://proxy:port'}
)
# 대안: tls_client
import tls_client
session = tls_client.Session(
client_identifier="chrome_108",
random_tls_extension_order=True
)
response = session.get('https://example.com')
HTTP/2 지문 인식
TLS 외에도 안티봇 시스템은 HTTP/2의 매개변수: 헤더 순서, SETTINGS 프레임 설정, 스트림 우선 순위를 분석합니다. 표준 라이브러리는 Chrome이나 Firefox의 정확한 헤더 순서를 준수하지 않습니다.
# Chrome에 대한 올바른 헤더 순서
headers = {
':method': 'GET',
':authority': 'example.com',
':scheme': 'https',
':path': '/',
'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'upgrade-insecure-requests': '1',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)...',
'accept': 'text/html,application/xhtml+xml...',
'sec-fetch-site': 'none',
'sec-fetch-mode': 'navigate',
'sec-fetch-user': '?1',
'sec-fetch-dest': 'document',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'en-US,en;q=0.9',
}
Canvas 및 WebGL 지문 인식
브라우저는 GPU, 드라이버 및 OS에 따라 그래픽을 다르게 렌더링합니다. 사이트는 이를 사용하여 장치의 고유한 지문을 생성합니다. 헤드리스 브라우저(Selenium, Puppeteer)를 사용할 때는 자동화의 징후를 숨기는 것이 중요합니다:
// Puppeteer: 헤드리스 모드 숨기기
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());
const browser = await puppeteer.launch({
headless: true,
args: [
'--disable-blink-features=AutomationControlled',
'--no-sandbox',
'--disable-setuid-sandbox',
`--proxy-server=${proxyUrl}`
]
});
const page = await browser.newPage();
// navigator.webdriver 재정의
await page.evaluateOnNewDocument(() => {
Object.defineProperty(navigator, 'webdriver', {
get: () => false,
});
});
헤더, 쿠키 및 세션 관리
HTTP 헤더 및 쿠키를 올바르게 처리하는 것은 실제 사용자 모방에 매우 중요합니다. 이러한 매개변수의 오류는 차단의 일반적인 원인입니다.
필수 헤더
Chrome 브라우저를 모방하기 위한 최소한의 헤더 세트:
import requests
headers = {
'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',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,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',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'none',
'Sec-Fetch-User': '?1',
'Cache-Control': 'max-age=0',
}
session = requests.Session()
session.headers.update(headers)
쿠키 관리
많은 사이트가 첫 방문 시 추적 쿠키를 설정하고 후속 요청 시 이를 확인합니다. 쿠키가 없거나 불일치하는 경우 봇의 징후입니다.
import requests
import pickle
class SessionManager:
def __init__(self, session_file='session.pkl'):
self.session_file = session_file
self.session = requests.Session()
self.load_session()
def load_session(self):
"""저장된 세션 로드"""
try:
with open(self.session_file, 'rb') as f:
cookies = pickle.load(f)
self.session.cookies.update(cookies)
except FileNotFoundError:
pass
def save_session(self):
"""재사용을 위한 쿠키 저장"""
with open(self.session_file, 'wb') as f:
pickle.dump(self.session.cookies, f)
def request(self, url, **kwargs):
response = self.session.get(url, **kwargs)
self.save_session()
return response
# 사용 예
manager = SessionManager('instagram_session.pkl')
response = manager.request('https://www.instagram.com/explore/')
중요: 프록시 회전 시 특정 IP에 연결된 쿠키를 재설정하는 것을 잊지 마세요. IP와 쿠키의 불일치(예: 미국 지리적 위치의 쿠키와 독일의 IP)는 의심을 유발할 수 있습니다.
Referer 및 Origin
Referer 및 Origin 헤더는 사용자가 어디에서 왔는지를 보여줍니다. 이들이 없거나 잘못된 값은 경고 신호입니다.
# 올바른 순서: 메인 → 카테고리 → 상품
session = requests.Session()
# 단계 1: 메인 페이지 방문
response = session.get('https://example.com/')
# 단계 2: 카테고리로 이동
response = session.get(
'https://example.com/category/electronics',
headers={'Referer': 'https://example.com/'}
)
# 단계 3: 상품 보기
response = session.get(
'https://example.com/product/12345',
headers={'Referer': 'https://example.com/category/electronics'}
)
인간 행동 모방
기술적 매개변수는 일의 절반에 불과합니다. 현대의 안티봇 시스템은 사용자가 페이지와 상호작용하는 방식, 페이지에서 보내는 시간, 마우스 움직임과 같은 행동 패턴을 분석합니다.
스크롤 및 마우스 움직임
Selenium 또는 Puppeteer를 사용할 때는 무작위 마우스 움직임과 페이지 스크롤을 추가하세요:
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import random
import time
def human_like_mouse_move(driver):
"""페이지에서 무작위로 마우스 움직임"""
action = ActionChains(driver)
for _ in range(random.randint(3, 7)):
x = random.randint(0, 1000)
y = random.randint(0, 800)
action.move_by_offset(x, y)
action.pause(random.uniform(0.1, 0.3))
action.perform()
def human_like_scroll(driver):
"""자연스러운 스크롤 모방"""
total_height = driver.execute_script("return document.body.scrollHeight")
current_position = 0
while current_position < total_height:
# 무작위 스크롤 단계
scroll_step = random.randint(100, 400)
current_position += scroll_step
driver.execute_script(f"window.scrollTo(0, {current_position});")
# 변동이 있는 대기
time.sleep(random.uniform(0.5, 1.5))
# 때때로 조금 뒤로 스크롤(사람들이 하는 것처럼)
if random.random() < 0.2:
back_scroll = random.randint(50, 150)
current_position -= back_scroll
driver.execute_script(f"window.scrollTo(0, {current_position});")
time.sleep(random.uniform(0.3, 0.8))
# 사용 예
driver = webdriver.Chrome()
driver.get('https://example.com')
human_like_mouse_move(driver)
time.sleep(random.uniform(2, 4))
human_like_scroll(driver)
페이지에서의 시간
실제 사용자는 페이지에서 시간을 보내며 콘텐츠를 읽고 이미지를 살펴봅니다. 링크를 즉시 클릭하는 봇은 쉽게 인식됩니다.
def realistic_page_view(driver, url, min_time=5, max_time=15):
"""
활동이 있는 현실적인 페이지 보기
"""
driver.get(url)
# 초기 지연 (로드 및 "읽기")
time.sleep(random.uniform(2, 4))
# 스크롤
human_like_scroll(driver)
# 추가 활동
total_time = random.uniform(min_time, max_time)
elapsed = 0
while elapsed < total_time:
action_choice = random.choice(['scroll', 'mouse_move', 'pause'])
if action_choice == 'scroll':
# 위/아래로 약간 스크롤
scroll_amount = random.randint(-200, 300)
driver.execute_script(f"window.scrollBy(0, {scroll_amount});")
pause = random.uniform(1, 3)
elif action_choice == 'mouse_move':
human_like_mouse_move(driver)
pause = random.uniform(0.5, 2)
else: # pause
pause = random.uniform(2, 5)
time.sleep(pause)
elapsed += pause
탐색 패턴
의심스러운 패턴을 피하세요: 깊은 페이지로의 직접 이동, 메인 페이지 무시, 모든 요소를 건너뛰지 않고 순차적으로 탐색.
좋은 관행:
- 메인 페이지 또는 인기 있는 섹션에서 시작하세요
- 직접 URL을 사용하는 대신 사이트의 내부 탐색을 사용하세요
- 때때로 뒤로 돌아가거나 다른 섹션으로 이동하세요
- 탐색 깊이를 다양화하세요: 항상 끝까지 가지 마세요
- "오류" 추가: 존재하지 않는 링크로 이동, 돌아가기
Cloudflare, DataDome 및 기타 보호 우회
전문 안티봇 시스템은 종합적인 접근 방식을 요구합니다. 이들은 JavaScript 챌린지, CAPTCHA, 실시간 행동 분석을 사용합니다.
Cloudflare
Cloudflare는 여러 보호 수준을 사용합니다: 브라우저 무결성 검사, JavaScript 챌린지, CAPTCHA. 기본 보호를 우회하려면 올바른 TLS 지문과 JavaScript 실행이 필요합니다:
# 옵션 1: cloudscraper (JS 챌린지 자동 해결)
import cloudscraper
scraper = cloudscraper.create_scraper(
browser={
'browser': 'chrome',
'platform': 'windows',
'desktop': True
}
)
response = scraper.get('https://protected-site.com')
# 옵션 2: undetected-chromedriver (복잡한 경우)
import undetected_chromedriver as uc
options = uc.ChromeOptions()
options.add_argument('--proxy-server=http://proxy:port')
driver = uc.Chrome(options=options)
driver.get('https://protected-site.com')
# 챌린지 통과 대기
time.sleep(5)
# requests를 위한 쿠키 가져오기
cookies = driver.get_cookies()
session = requests.Session()
for cookie in cookies:
session.cookies.set(cookie['name'], cookie['value'])
DataDome
DataDome은 사용자의 행동을 실시간으로 분석합니다: 마우스 움직임, 키보드 타이핑, 타이밍. 우회를 위해서는 활동을 모방하는 완전한 브라우저가 필요합니다:
from playwright.sync_api import sync_playwright
import random
def bypass_datadome(url, proxy=None):
with sync_playwright() as p:
browser = p.chromium.launch(
headless=False, # DataDome은 헤드리스 모드를 감지합니다
proxy={'server': proxy} if proxy else None
)
context = browser.new_context(
viewport={'width': 1920, 'height': 1080},
user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64)...'
)
page = context.new_page()
# 자동화 숨기기 위한 스크립트 주입
page.add_init_script("""
Object.defineProperty(navigator, 'webdriver', {get: () => false});
window.chrome = {runtime: {}};
""")
page.goto(url)
# 인간 행동 모방
time.sleep(random.uniform(2, 4))
# 무작위 마우스 움직임
for _ in range(random.randint(5, 10)):
page.mouse.move(
random.randint(100, 1800),
random.randint(100, 1000)
)
time.sleep(random.uniform(0.1, 0.3))
# 스크롤
page.evaluate(f"window.scrollTo(0, {random.randint(300, 800)})")
time.sleep(random.uniform(1, 2))
content = page.content()
browser.close()
return content
CAPTCHA
CAPTCHA를 자동으로 해결하려면 인식 서비스(2captcha, Anti-Captcha)를 사용하거나 회피 전략을 사용하세요:
- CAPTCHA를 유발하지 않는 수준으로 요청 빈도를 줄이세요
- 좋은 평판을 가진 깨끗한 주거용 IP를 사용하세요
- 인증된 계정을 통해 작업하세요 (이들은 CAPTCHA 임계값이 더 높습니다)
- 시간에 따라 부하를 분산하세요 (피크 시간을 피하세요)
모니터링 및 차단 처리
최고의 관행을 사용하더라도 차단은 불가피합니다. 이를 신속하게 발견하고 올바르게 처리하는 것이 중요합니다.
차단 신호
| 신호 | 설명 | 조치 |
|---|---|---|
| HTTP 429 | 요청이 너무 많음 | 지연 증가, IP 변경 |
| HTTP 403 | 금지됨 (IP 차단) | 프록시 변경, 지문 확인 |
| CAPTCHA | 검증 필요 | 해결 또는 활동 줄이기 |
| 빈 응답 | 콘텐츠가 로드되지 않음 | JavaScript, 쿠키 확인 |
| /blocked로 리디렉션 | 명백한 차단 | 전략 완전 변경 |
재시도 시스템
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
def create_session_with_retries():
"""
자동 재시도 및 오류 처리가 있는 세션
"""
session = requests.Session()
retry_strategy = Retry(
total=5,
backoff_factor=2, # 2, 4, 8, 16, 32 초
status_forcelist=[429, 500, 502, 503, 504],
method_whitelist=["GET", "POST"]
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("http://", adapter)
session.mount("https://", adapter)
return session
def safe_request(url, session, max_attempts=3):
"""
차단 처리와 함께 요청
"""
for attempt in range(max_attempts):
try:
response = session.get(url, timeout=15)
# 차단 확인
if response.status_code == 403:
print(f"IP 차단됨. 프록시 회전 중...")
# 프록시 변경 로직
continue
elif response.status_code == 429:
wait_time = int(response.headers.get('Retry-After', 60))
print(f"요청 속도 제한. {wait_time}s 대기 중...")
time.sleep(wait_time)
continue
elif 'captcha' in response.text.lower():
print("CAPTCHA 감지됨")
# CAPTCHA 해결 또는 건너뛰기 로직
return None
return response
except requests.exceptions.Timeout:
print(f"시도 {attempt + 1}에서 시간 초과")
time.sleep(5 * (attempt + 1))
except requests.exceptions.ProxyError:
print("프록시 오류. 회전 중...")
# 프록시 변경
continue
return None
로깅 및 분석
전략 최적화를 위한 메트릭을 추적하세요:
import logging
from collections import defaultdict
from datetime import datetime
class ScraperMetrics:
def __init__(self):
self.stats = {
'total_requests': 0,
'successful': 0,
'rate_limited': 0,
'blocked': 0,
'captcha': 0,
'errors': 0,
'proxy_failures': defaultdict(int)
}
def log_request(self, status, proxy=None):
self.stats['total_requests'] += 1
if status == 200:
self.stats['successful'] += 1
elif status == 429:
self.stats['rate_limited'] += 1
elif status == 403:
self.stats['blocked'] += 1
if proxy:
self.stats['proxy_failures'][proxy] += 1
def get_success_rate(self):
if self.stats['total_requests'] == 0:
return 0
return (self.stats['successful'] / self.stats['total_requests']) * 100
def print_report(self):
print(f"\n=== 스크래핑 보고서 ===")
print(f"총 요청: {self.stats['total_requests']}")
print(f"성공률: {self.get_success_rate():.2f}%")
print(f"요청 속도 제한: {self.stats['rate_limited']}")
print(f"차단됨: {self.stats['blocked']}")
print(f"CAPTCHA: {self.stats['captcha']}")
if self.stats['proxy_failures']:
print(f"\n문제가 있는 프록시:")
for proxy, count in sorted(
self.stats['proxy_failures'].items(),
key=lambda x: x[1],
reverse=True
)[:5]:
print(f" {proxy}: {count} 실패")
# 사용 예
metrics = ScraperMetrics()
for url in urls:
response = safe_request(url, session)
if response:
metrics.log_request(response.status_code, current_proxy)
metrics.print_report()
최적의 지표: 성공률 95% 이상은 훌륭한 결과입니다. 80-95%는 수용 가능하지만 개선할 여지가 있습니다. 80% 이하인 경우 전략을 재검토하세요: 너무 공격적인 요청 속도 제한, 나쁜 프록시 또는 지문 문제일 수 있습니다.
결론
차단 방지 전략은 복잡하고 지속적으로 발전하는 환경에서 효과적으로 작동해야 합니다. 위에서 언급한 기술과 도구를 활용하여 보다 안전하고 효과적인 자동화 작업을 수행할 수 있습니다.