Thực thi JavaScript và các kỹ thuật ẩn danh WebDriver trong Selenium

Thực thi mã JavaScript trong Selenium

Selenium cho phép tương tác trực tiếp với môi trường trình duyệt bằng cách thực thi các đoạn mã JavaScript. Điều này đặc biệt hữu ích khi cần thao tác với DOM, gọi các hàm nội bộ của trang web hoặc mô phỏng các hành vi phức tạp của người dùng.

# Cú pháp cơ bản để thực thi JS trong ngữ cảnh trình duyệt
driver_instance.execute_script('console.log("Đang thực thi mã JavaScript");')

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

Các trang web hiện đại thường sử dụng JavaScript để kiểm tra xem trình duyệt có đang bị điều khiển bởi công cụ tự động hay không. Dấu hiệu rõ ràng và phổ biến nhất là thuộc tính window.navigator.webdriver.

  • Trình duyệt bình thường: window.navigator.webdriver trả về undefined hoặc false.
  • Trình duyệt tự động hóa: window.navigator.webdriver trả về true.

Ngoài ra, các hệ thống chống bot còn quét hàng loạt biến nội bộ và chuỗi đặc trưng được tiêm bởi các driver như ChromeDriver, GeckoDriver. Một số dấu vết phổ biến bao gồm:

__driver_evaluate, __webdriver_evaluate, __selenium_evaluate, 
__fxdriver_evaluate, __driver_unwrapped, __webdriver_unwrapped, 
_Selenium_IDE_Recorder, _WEBDRIVER_ELEM_CACHE, $cdc_asdjflasutopfhvcZLmcfl_

Nếu phát hiện các chuỗi này, máy chủ sẽ đánh dấu request là đến từ bot và chặn truy cập hoặc yêu cầu xác thực CAPTCHA.

Kỹ thuật 1: Cấu hình ChromeOptions để loại bỏ dấu vết tự động hóa

Cách cơ bản nhất là tắt các cờ (flags) thông báo chế độ tự động hóa và tắt tải các tài nguyên không cần thiết như hình ảnh để tăng hiệu suất và giảm thiểu fingerprint.

from selenium import webdriver

# Thiết lập các tùy chọn cho Chrome
chrome_configs = webdriver.ChromeOptions()

# Loại bỏ thông báo "Chrome đang bị điều khiển bởi phần mềm tự động hóa"
chrome_configs.add_experimental_option('excludeSwitches', ['enable-automation'])
chrome_configs.add_experimental_option('useAutomationExtension', False)

# Chặn tải hình ảnh để giảm băng thông và tăng tốc độ xử lý
prefs = {"profile.managed_default_content_settings.images": 2}
chrome_configs.add_experimental_option("prefs", prefs)

# Khởi tạo phiên làm việc
web_driver = webdriver.Chrome(options=chrome_configs)
web_driver.get("https://example-ecommerce.com")

Kỹ thuật 2: Kết nối tới trình duyệt qua Remote Debugging

Thay vì để Selenium khởi tạo một trình duyệt mới (sẽ sinh ra fingerprint của WebDriver), ta có thể kết nối tới một phiên Chrome đang chạy sẵn bằng chế độ Remote Debugging. Cách này giúp trình duyệt giữ nguyên trạng thái của người dùng thật và không mang các đặc điểm của automation.

Bước 1: Khởi động Chrome thủ công qua Command Line hoặc Terminal:

chrome.exe --remote-debugging-port=9333 --user-data-dir="C:\temp\chrome_stealth_profile"

Bước 2: Sử dụng Python để kết nối vào cổng debug đã mở:

from selenium import webdriver

# Cấu hình địa chỉ debug
debug_options = webdriver.ChromeOptions()
debug_options.add_experimental_option('debuggerAddress', '127.0.0.1:9333')

# Kết nối tới phiên Chrome đang chạy mà không cần khởi tạo driver mới
remote_driver = webdriver.Chrome(options=debug_options)
remote_driver.get("https://example-social-network.com")

Kỹ thuật 3: Sử dụng CDP ghi đè thuộc tính navigator.webdriver

Sử dụng Chrome DevTools Protocol (CDP) để chèn một đoạn mã JavaScript thực thi ngay trước khi tài liệu được tải. Đoạn mã này sẽ định nghĩa lại getter của navigator.webdriver để luôn trả về undefined, đánh lừa các script kiểm tra anti-bot.

import time
from selenium import webdriver

def run_stealth_selenium(target_url, custom_js):
    stealth_opts = webdriver.ChromeOptions()
    stealth_opts.add_experimental_option('excludeSwitches', ['enable-automation'])
    stealth_opts.add_experimental_option('useAutomationExtension', False)

    driver = webdriver.Chrome(options=stealth_opts)

    # Sử dụng CDP để chèn script ẩn danh trước khi tải trang
    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
        "source": """
            Object.defineProperty(navigator, 'webdriver', {
                get: () => undefined
            });
        """
    })

    driver.implicitly_wait(15)
    driver.get(target_url)
    time.sleep(3)

    print(driver.page_source)
    if custom_js:
        driver.execute_script(custom_js)

# Khởi chạy tác vụ
run_stealth_selenium("https://example-news-portal.com", "return document.title;")

Thẻ: selenium webdriver-detection chrome-devtools-protocol web-scraping python-automation

Đăng vào ngày 3 tháng 9 lúc 03:52