Quay lại blog

Cách tránh bị chặn khi gửi yêu cầu hàng loạt

Phân tích cơ chế phát hiện tự động hóa và các kỹ thuật bảo vệ chống lại việc chặn khi gửi yêu cầu hàng loạt: từ việc xoay vòng proxy cơ bản đến việc giả lập hành vi con người.

📅21 tháng 12, 2025
```html

Bảo vệ khỏi việc bị chặn khi gửi yêu cầu hàng loạt: kỹ thuật và công cụ

Việc chặn tài khoản và địa chỉ IP là vấn đề chính khi thu thập dữ liệu, tự động hóa và thực hiện các thao tác hàng loạt trên mạng xã hội. Các hệ thống chống bot hiện đại phân tích hàng chục thông số: từ tần suất yêu cầu đến dấu vân tay trình duyệt. Trong hướng dẫn này, chúng ta sẽ phân tích các cơ chế phát hiện tự động hóa và các cách thực tế để vượt qua chúng.

Cơ chế phát hiện tự động hóa

Các hệ thống bảo vệ hiện đại sử dụng phân tích đa tầng để phát hiện bot. Hiểu rõ những cơ chế này là rất quan trọng để chọn lựa chiến lược vượt qua phù hợp.

Các thông số phân tích chính

Danh tiếng IP: Các hệ thống chống bot kiểm tra lịch sử địa chỉ IP, thuộc về các trung tâm dữ liệu, có mặt trong danh sách đen hay không. IP từ các nhóm proxy nổi tiếng thường bị chặn nhiều hơn.

Tần suất yêu cầu (Request Rate): Con người không thể gửi 100 yêu cầu mỗi phút. Các hệ thống phân tích không chỉ tổng số lượng mà còn cả sự phân bố theo thời gian — các khoảng thời gian đều đặn giữa các yêu cầu sẽ phát hiện bot.

Mô hình hành vi: Chuỗi hành động, độ sâu cuộn trang, chuyển động chuột, thời gian trên trang. Bot chuyển tiếp liên kết ngay lập tức mà không có độ trễ sẽ dễ dàng bị phát hiện.

Dấu vân tay kỹ thuật: User-Agent, tiêu đề HTTP, thứ tự tiêu đề, dấu vân tay TLS, dấu vân tay Canvas/WebGL. Sự không khớp trong các thông số này là tín hiệu đỏ cho các hệ thống chống bot.

Thông số Nội dung phân tích Rủi ro phát hiện
Địa chỉ IP Danh tiếng, ASN, định vị địa lý Cao
User-Agent Phiên bản trình duyệt, HĐH, thiết bị Trung bình
Dấu vân tay TLS Tập hợp mã hóa, mở rộng Cao
Dấu vân tay HTTP/2 Thứ tự tiêu đề, cài đặt Cao
Canvas/WebGL Vẽ đồ họa Trung bình
Hành vi Nhấp chuột, cuộn trang, thời gian Cao

Giới hạn tốc độ và kiểm soát tần suất yêu cầu

Kiểm soát tốc độ gửi yêu cầu là hàng rào bảo vệ đầu tiên chống lại việc bị chặn. Ngay cả khi xoay vòng proxy, việc thu thập dữ liệu quá mức sẽ dẫn đến việc bị cấm.

Độ trễ động

Các khoảng thời gian cố định (ví dụ: đúng 2 giây giữa các yêu cầu) dễ dàng bị phát hiện. Sử dụng độ trễ ngẫu nhiên với phân phối chuẩn:

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):
    """
    Tạo độ trễ với phân phối chuẩn
    mô phỏng hành vi con người
    """
    delay = np.random.normal(mean, std)
    # Giới hạn khoảng
    delay = max(min_delay, min(delay, max_delay))
    
    # Thêm độ trễ vi mô để thực tế hơn
    delay += random.uniform(0, 0.3)
    
    time.sleep(delay)

# Sử dụng
for url in urls:
    response = session.get(url)
    human_delay(min_delay=2, max_delay=5, mean=3, std=1)

Giới hạn tốc độ thích ứng

Một cách tiếp cận tiên tiến hơn là điều chỉnh tốc độ dựa trên phản hồi từ máy chủ. Nếu nhận được mã 429 (Quá nhiều yêu cầu) hoặc 503, hãy tự động giảm tốc độ:

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):
        # Tăng tốc độ dần dần khi có yêu cầu thành công
        self.current_delay = max(
            self.min_delay, 
            self.current_delay * 0.95
        )
        self.error_count = 0
        
    def on_rate_limit(self):
        # Giảm tốc độ ngay lập tức khi bị chặn
        self.error_count += 1
        self.current_delay = min(
            self.max_delay,
            self.current_delay * (1.5 + self.error_count * 0.5)
        )
        print(f"Đã đạt giới hạn tốc độ. Độ trễ mới: {self.current_delay:.2f}s")

# Áp dụng
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)  # Tạm dừng trước khi thử lại
    elif response.status_code == 200:
        limiter.on_success()
    else:
        # Xử lý các lỗi khác
        pass

Lời khuyên thực tế: Tốc độ tối ưu khác nhau cho các trang web khác nhau. Các nền tảng lớn (Google, Facebook) có thể chịu đựng 5-10 yêu cầu mỗi phút từ một IP. Các trang nhỏ có thể chặn ngay cả khi có 20-30 yêu cầu mỗi giờ. Luôn bắt đầu một cách thận trọng và từ từ tăng tải, theo dõi tỷ lệ lỗi.

Xoay vòng proxy và quản lý địa chỉ IP

Sử dụng một địa chỉ IP cho các yêu cầu hàng loạt đảm bảo sẽ bị chặn. Xoay vòng proxy phân phối tải và giảm rủi ro phát hiện.

Chiến lược xoay vòng

1. Xoay vòng theo yêu cầu: Thay đổi IP sau mỗi yêu cầu hoặc sau mỗi N yêu cầu. Phù hợp cho việc thu thập dữ liệu từ các công cụ tìm kiếm, nơi mà sự ẩn danh của mỗi yêu cầu là quan trọng.

2. Xoay vòng theo thời gian: Thay đổi IP mỗi 5-15 phút. Hiệu quả cho việc làm việc với mạng xã hội, nơi mà sự ổn định của phiên làm việc là quan trọng.

3. Phiên làm việc dính: Sử dụng một IP cho toàn bộ phiên làm việc của người dùng (đăng nhập, chuỗi hành động). Rất quan trọng cho các trang web có bảo vệ chống CSRF.

import requests
from itertools import cycle

class ProxyRotator:
    def __init__(self, proxy_list, rotation_type='request', rotation_interval=10):
        """
        rotation_type: 'request' (mỗi yêu cầu) hoặc 'time' (theo thời gian)
        rotation_interval: số lượng yêu cầu hoặc giây
        """
        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"Đã xoay vòng đến: {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"Đã xoay vòng đến: {self.current_proxy}")
                
        return {'http': self.current_proxy, 'https': self.current_proxy}

# Ví dụ sử dụng
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)

Lựa chọn loại proxy

Loại proxy Mức độ tin cậy Tốc độ Ứng dụng
Trung tâm dữ liệu Thấp Cao Thu thập dữ liệu đơn giản, API
Proxy dân cư Cao Trung bình Mạng xã hội, trang web bảo mật
Proxy di động Rất cao Trung bình Instagram, TikTok, chống gian lận

Đối với các hoạt động hàng loạt trên mạng xã hội và trên các nền tảng có bảo vệ nghiêm ngặt, hãy sử dụng proxy dân cư. Chúng trông giống như các kết nối gia đình thông thường và hiếm khi bị đưa vào danh sách đen. Trung tâm dữ liệu phù hợp cho các tài nguyên ít bảo mật hơn, nơi tốc độ là quan trọng.

Dấu vân tay trình duyệt và dấu vân tay TLS

Ngay cả khi xoay vòng IP, bạn có thể bị phát hiện qua các dấu vân tay kỹ thuật của trình duyệt và kết nối TLS. Những thông số này là duy nhất cho mỗi khách hàng và khó giả mạo.

Dấu vân tay TLS

Khi thiết lập kết nối HTTPS, khách hàng gửi ClientHello với tập hợp các mã hóa và mở rộng được hỗ trợ. Sự kết hợp này là duy nhất cho mỗi thư viện. Ví dụ, Python requests sử dụng OpenSSL, dấu vân tay của nó dễ dàng phân biệt với Chrome.

Vấn đề: Các thư viện tiêu chuẩn (requests, urllib, curl) có dấu vân tay khác với các trình duyệt thực tế. Các dịch vụ như Cloudflare, Akamai, DataDome tích cực sử dụng dấu vân tay TLS để chặn bot.

Giải pháp: Sử dụng các thư viện mô phỏng dấu vân tay TLS của trình duyệt. Đối với Python, có thể sử dụng curl_cffi, tls_client hoặc playwright/puppeteer để mô phỏng hoàn toàn trình duyệt.

# Cài đặt: pip install curl-cffi
from curl_cffi import requests

# Mô phỏng Chrome 110
response = requests.get(
    'https://example.com',
    impersonate="chrome110",
    proxies={'https': 'http://proxy:port'}
)

# Thay thế: tls_client
import tls_client

session = tls_client.Session(
    client_identifier="chrome_108",
    random_tls_extension_order=True
)

response = session.get('https://example.com')

Dấu vân tay HTTP/2

Ngoài TLS, các hệ thống chống bot phân tích các thông số HTTP/2: thứ tự tiêu đề, cài đặt SETTINGS frame, ưu tiên luồng. Các thư viện tiêu chuẩn không tuân thủ thứ tự tiêu đề chính xác của Chrome hoặc Firefox.

# Thứ tự tiêu đề đúng cho 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',
}

Dấu vân tay Canvas và WebGL

Các trình duyệt vẽ đồ họa khác nhau tùy thuộc vào GPU, trình điều khiển và HĐH. Các trang web sử dụng điều này để tạo ra dấu vân tay thiết bị duy nhất. Khi sử dụng các trình duyệt headless (Selenium, Puppeteer), việc che giấu các dấu hiệu tự động hóa là rất quan trọng:

// Puppeteer: ẩn chế độ headless
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();

// Ghi đè navigator.webdriver
await page.evaluateOnNewDocument(() => {
    Object.defineProperty(navigator, 'webdriver', {
        get: () => false,
    });
});

Tiêu đề, cookies và quản lý phiên làm việc

Việc xử lý chính xác các tiêu đề HTTP và cookies là rất quan trọng để mô phỏng người dùng thực. Các lỗi trong các thông số này là nguyên nhân phổ biến gây ra việc bị chặn.

Các tiêu đề bắt buộc

Tập hợp tiêu đề tối thiểu để mô phỏng trình duyệt 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)

Quản lý cookies

Nhiều trang web thiết lập tracking cookies khi lần đầu truy cập và kiểm tra sự tồn tại của chúng trong các yêu cầu tiếp theo. Việc thiếu cookies hoặc không khớp là dấu hiệu của bot.

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):
        """Tải phiên đã lưu"""
        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):
        """Lưu cookies để sử dụng lại"""
        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

# Sử dụng
manager = SessionManager('instagram_session.pkl')
response = manager.request('https://www.instagram.com/explore/')

Quan trọng: Khi xoay vòng proxy, đừng quên đặt lại cookies nếu chúng liên kết với một IP cụ thể. Sự không khớp giữa IP và cookies (ví dụ, cookies với định vị địa lý ở Mỹ và IP từ Đức) sẽ gây nghi ngờ.

Referer và Origin

Các tiêu đề RefererOrigin cho biết người dùng đến từ đâu. Việc thiếu hoặc giá trị không chính xác là tín hiệu đỏ.

# Thứ tự đúng: trang chính → danh mục → sản phẩm
session = requests.Session()

# Bước 1: truy cập trang chính
response = session.get('https://example.com/')

# Bước 2: chuyển đến danh mục
response = session.get(
    'https://example.com/category/electronics',
    headers={'Referer': 'https://example.com/'}
)

# Bước 3: xem sản phẩm
response = session.get(
    'https://example.com/product/12345',
    headers={'Referer': 'https://example.com/category/electronics'}
)

Mô phỏng hành vi con người

Các thông số kỹ thuật chỉ là một nửa của vấn đề. Các hệ thống chống bot hiện đại phân tích các mẫu hành vi: cách người dùng tương tác với trang, thời gian họ dành cho trang, cách di chuyển chuột.

Cuộn trang và di chuyển chuột

Khi sử dụng Selenium hoặc Puppeteer, hãy thêm các chuyển động chuột ngẫu nhiên và cuộn trang:

from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import random
import time

def human_like_mouse_move(driver):
    """Di chuyển chuột ngẫu nhiên trên trang"""
    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):
    """Mô phỏng cuộn tự nhiên"""
    total_height = driver.execute_script("return document.body.scrollHeight")
    current_position = 0
    
    while current_position < total_height:
        # Bước cuộn ngẫu nhiên
        scroll_step = random.randint(100, 400)
        current_position += scroll_step
        
        driver.execute_script(f"window.scrollTo(0, {current_position});")
        
        # Tạm dừng với biến thể
        time.sleep(random.uniform(0.5, 1.5))
        
        # Đôi khi cuộn ngược lại một chút (như con người làm)
        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))

# Sử dụng
driver = webdriver.Chrome()
driver.get('https://example.com')

human_like_mouse_move(driver)
time.sleep(random.uniform(2, 4))
human_like_scroll(driver)

Thời gian trên trang

Người dùng thực sự dành thời gian trên trang: đọc nội dung, xem hình ảnh. Bot chuyển tiếp liên kết ngay lập tức sẽ dễ dàng bị phát hiện.

def realistic_page_view(driver, url, min_time=5, max_time=15):
    """
    Xem trang một cách thực tế với hoạt động
    """
    driver.get(url)
    
    # Độ trễ ban đầu (tải và "đọc")
    time.sleep(random.uniform(2, 4))
    
    # Cuộn trang
    human_like_scroll(driver)
    
    # Hoạt động bổ sung
    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':
            # Cuộn nhẹ lên/xuống
            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

Mẫu điều hướng

Tránh các mẫu đáng ngờ: chuyển tiếp trực tiếp đến các trang sâu, bỏ qua trang chính, duyệt tất cả các phần tử mà không bỏ lỡ.

Thực hành tốt:

  • Bắt đầu từ trang chính hoặc các phần phổ biến
  • Sử dụng điều hướng nội bộ của trang web, không phải URL trực tiếp
  • Đôi khi quay lại hoặc chuyển đến các phần khác
  • Thay đổi độ sâu xem: không phải lúc nào cũng đến cuối
  • Thêm "lỗi": chuyển tiếp đến các liên kết không tồn tại, quay lại

Vượt qua Cloudflare, DataDome và các biện pháp bảo vệ khác

Các hệ thống chống bot chuyên dụng yêu cầu một cách tiếp cận toàn diện. Chúng sử dụng các thử thách JavaScript, CAPTCHA, phân tích hành vi trong thời gian thực.

Cloudflare

Cloudflare sử dụng nhiều lớp bảo vệ: Kiểm tra tính toàn vẹn của trình duyệt, Thử thách JavaScript, CAPTCHA. Để vượt qua bảo vệ cơ bản, chỉ cần có dấu vân tay TLS chính xác và thực hiện JavaScript:

# Phương án 1: cloudscraper (giải quyết tự động các thử thách JS)
import cloudscraper

scraper = cloudscraper.create_scraper(
    browser={
        'browser': 'chrome',
        'platform': 'windows',
        'desktop': True
    }
)

response = scraper.get('https://protected-site.com')

# Phương án 2: undetected-chromedriver (cho các trường hợp phức tạp)
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')

# Chờ đợi vượt qua thử thách
time.sleep(5)

# Lấy cookies cho requests
cookies = driver.get_cookies()
session = requests.Session()
for cookie in cookies:
    session.cookies.set(cookie['name'], cookie['value'])

DataDome

DataDome phân tích hành vi người dùng trong thời gian thực: chuyển động chuột, chữ ký bàn phím, thời gian. Để vượt qua, cần có một trình duyệt hoàn chỉnh với mô phỏng hoạt động:

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 phát hiện headless
            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()
        
        # Tiêm mã để che giấu tự động hóa
        page.add_init_script("""
            Object.defineProperty(navigator, 'webdriver', {get: () => false});
            window.chrome = {runtime: {}};
        """)
        
        page.goto(url)
        
        # Mô phỏng hành vi con người
        time.sleep(random.uniform(2, 4))
        
        # Di chuyển chuột ngẫu nhiên
        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))
        
        # Cuộn trang
        page.evaluate(f"window.scrollTo(0, {random.randint(300, 800)})")
        time.sleep(random.uniform(1, 2))
        
        content = page.content()
        browser.close()
        
        return content

CAPTCHA

Để giải quyết CAPTCHA tự động, hãy sử dụng các dịch vụ nhận diện (2captcha, Anti-Captcha) hoặc các chiến lược tránh né:

  • Giảm tần suất yêu cầu xuống mức không gây ra CAPTCHA
  • Sử dụng IP dân cư sạch với danh tiếng tốt
  • Làm việc qua các tài khoản đã được xác thực (có ngưỡng CAPTCHA cao hơn)
  • Phân phối tải theo thời gian (tránh giờ cao điểm)

Giám sát và xử lý việc bị chặn

Ngay cả với các thực hành tốt nhất, việc bị chặn là không thể tránh khỏi. Quan trọng là phát hiện nhanh chóng và xử lý đúng cách.

Các chỉ số bị chặn

Tín hiệu Mô tả Hành động
HTTP 429 Quá nhiều yêu cầu Tăng độ trễ, thay đổi IP
HTTP 403 Bị cấm (IP bị chặn) Thay đổi proxy, kiểm tra fingerprint
CAPTCHA Cần xác thực Giải quyết hoặc giảm hoạt động
Phản hồi trống Nội dung không tải được Kiểm tra JavaScript, cookies
Chuyển hướng đến /blocked Bị chặn rõ ràng Thay đổi hoàn toàn chiến lược

Hệ thống thử lại

import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry

def create_session_with_retries():
    """
    Phiên làm việc với các lần thử tự động và xử lý lỗi
    """
    session = requests.Session()
    
    retry_strategy = Retry(
        total=5,
        backoff_factor=2,  # 2, 4, 8, 16, 32 giây
        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):
    """
    Yêu cầu với xử lý việc bị chặn
    """
    for attempt in range(max_attempts):
        try:
            response = session.get(url, timeout=15)
            
            # Kiểm tra việc bị chặn
            if response.status_code == 403:
                print(f"IP bị chặn. Đang xoay vòng proxy...")
                # Logic thay đổi proxy
                continue
                
            elif response.status_code == 429:
                wait_time = int(response.headers.get('Retry-After', 60))
                print(f"Đã đạt giới hạn tốc độ. Đợi {wait_time}s...")
                time.sleep(wait_time)
                continue
                
            elif 'captcha' in response.text.lower():
                print("Đã phát hiện CAPTCHA")
                # Logic giải quyết CAPTCHA hoặc bỏ qua
                return None
                
            return response
            
        except requests.exceptions.Timeout:
            print(f"Hết thời gian ở lần thử {attempt + 1}")
            time.sleep(5 * (attempt + 1))
            
        except requests.exceptions.ProxyError:
            print("Lỗi proxy. Đang xoay vòng...")
            # Thay đổi proxy
            continue
            
    return None

Ghi log và phân tích

Theo dõi các chỉ số để tối ưu hóa chiến lược:

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=== Báo cáo thu thập dữ liệu ===")
        print(f"Tổng số yêu cầu: {self.stats['total_requests']}")
        print(f"Tỷ lệ thành công: {self.get_success_rate():.2f}%")
        print(f"Bị giới hạn tốc độ: {self.stats['rate_limited']}")
        print(f"Bị chặn: {self.stats['blocked']}")
        print(f"CAPTCHA: {self.stats['captcha']}")
        
        if self.stats['proxy_failures']:
            print(f"\nCác proxy gặp vấn đề:")
            for proxy, count in sorted(
                self.stats['proxy_failures'].items(), 
                key=lambda x: x[1], 
                reverse=True
            )[:5]:
                print(f"  {proxy}: {count} lần thất bại")

# Sử dụng
metrics = ScraperMetrics()

for url in urls:
    response = safe_request(url, session)
    if response:
        metrics.log_request(response.status_code, current_proxy)
    
metrics.print_report()

Các chỉ số tối ưu: Tỷ lệ thành công trên 95% — kết quả tuyệt vời. 80-95% — chấp nhận được, nhưng cần cải thiện. Dưới 80% — xem xét lại chiến lược: có thể là giới hạn tốc độ quá mức, proxy kém hoặc vấn đề với dấu vân tay.

Kết luận

Bảo vệ khỏi việc bị chặn khi gửi yêu cầu hàng loạt là một quá trình phức tạp, yêu cầu sự hiểu biết sâu sắc về các cơ chế phát hiện và các chiến lược vượt qua. Bằng cách áp dụng các kỹ thuật và công cụ đã đề cập trong bài viết này, bạn có thể giảm thiểu rủi ro và tối ưu hóa hiệu suất thu thập dữ liệu của mình.

```