Selenium là gì?
Selenium là một công cụ mạnh mẽ dùng để kiểm thử ứng dụng Web, có khả năng mô phỏng hành vi người dùng thật thông qua thao tác trực tiếp trên trình duyệt. Nó hỗ trợ nhiều trình duyệt phổ biến như Google Chrome, Mozilla Firefox, Safari, Opera và Internet Explorer trên các hệ điều hành khác nhau. Các tính năng chính bao gồm:
- Kiểm tra tương thích giữa ứng dụng và nhiều loại trình duyệt.
- Tự động hóa quy trình kiểm thử chức năng (regression testing).
- Hỗ trợ ghi lại thao tác và sinh mã kiểm thử bằng nhiều ngôn ngữ lập trình như Java, .NET, Python, Perl…
Ứng dụng của Selenium trong web scraping
Trong lĩnh vực thu thập dữ liệu, Selenium được sử dụng rộng rãi nhờ khả năng xử lý nội dung tải động (dynamic content) mà các công cụ truyền thống như requests + BeautifulSoup không thể truy cập được. Ưu điểm nổi bật:
- Thu thập dữ liệu động: Dữ liệu nào hiển thị trên giao diện người dùng đều có thể lấy được.
- Thực hiện đăng nhập tự động: Xử lý xác thực phức tạp như form JavaScript, reCAPTCHA (kết hợp với giải pháp khác), hoặc đăng nhập OAuth.
Cài đặt và cấu hình cơ bản
Để bắt đầu sử dụng Selenium với Python, cần thực hiện các bước sau:
- Cài đặt thư viện:
pip install selenium - Tải về phiên bản phù hợp của trình điều khiển (driver) cho trình duyệt mong muốn (ví dụ: ChromeDriver cho Google Chrome).
- Đảm bảo phiên bản driver tương thích với phiên bản trình duyệt đang sử dụng.
Ví dụ cơ bản với Python
Dưới đây là đoạn mã minh họa cách mở trang Baidu, thao tác với cài đặt, nhập từ khóa tìm kiếm và điều hướng đến kết quả:
from time import sleep
from selenium import webdriver
# Khởi tạo trình điều khiển Chrome
driver = webdriver.Chrome(executable_path=r'chromedriver.exe')
# Mở trang chủ Baidu
driver.get("https://www.baidu.com")
# Nhấp vào menu "Cài đặt"
driver.find_element_by_xpath('//*[@id="s-usersetting-top"]').click()
sleep(1)
# Vào mục "Cài đặt tìm kiếm"
driver.find_element_by_link_text("Cài đặt tìm kiếm").click()
sleep(1)
# Chọn tùy chọn hiển thị 50 kết quả mỗi trang
driver.find_element_by_xpath('//input[@value="50"]').click()
sleep(1)
# Lưu thay đổi
driver.find_element_by_class_name("prefpanelgo").click()
# Xử lý popup cảnh báo (nếu có)
try:
alert = driver.switch_to.alert
alert.accept()
except:
pass
# Tìm ô tìm kiếm, nhập từ khóa và thực hiện tìm
search_box = driver.find_element_by_id("kw")
search_box.send_keys("hình ảnh đẹp")
sleep(1)
search_button = driver.find_element_by_id("su")
search_button.click()
sleep(2)
# Mở liên kết đầu tiên trong kết quả tìm kiếm
first_result = driver.find_element_by_xpath('//*[@id="1"]/h3/a')
first_result.click()
# Giữ cửa sổ mở trong 10 giây để quan sát
sleep(10)
# Đóng trình duyệt
driver.quit()
Tương tác với các phần tử và thực thi JavaScript
Selenium cho phép định vị phần tử bằng nhiều cách: ID, class name, XPath, CSS selector… Ngoài ra, có thể thực thi đoạn mã JavaScript để thao tác sâu hơn với trang web:
from selenium import webdriver
import time
browser = webdriver.Chrome(executable_path='chromedriver.exe')
browser.get('https://www.jd.com')
# Tìm ô tìm kiếm và nhập nội dung
input_field = browser.find_element_by_css_selector('#key')
input_field.send_keys('MacBook Pro')
# Nhấn nút tìm kiếm
search_btn = browser.find_element_by_css_selector('.button')
search_btn.click()
time.sleep(2)
# Cuộn xuống cuối trang bằng JavaScript
browser.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(2)
# Lấy mã nguồn HTML sau khi đã render đầy đủ
html_content = browser.page_source
# In nội dung (có thể phân tích bằng BeautifulSoup nếu cần)
print(html_content[:1000]) # In 1000 ký tự đầu
browser.quit()
Thu thập dữ liệu từ trang phân trang động
Một số trang web tải dữ liệu theo từng trang thông qua AJAX. Selenium giúp lặp lại thao tác nhấn nút "Trang tiếp" để thu thập toàn bộ dữ liệu:
from selenium import webdriver
import time
from lxml import etree
driver = webdriver.Chrome(executable_path='chromedriver.exe')
driver.get('http://125.35.6.84:81/xk/')
time.sleep(2)
pages_html = []
for _ in range(4): # Thu thập 4 trang
pages_html.append(driver.page_source)
try:
next_btn = driver.find_element_by_id('pageIto_next')
next_btn.click()
time.sleep(1.5)
except:
break # Dừng nếu không còn nút tiếp
# Phân tích từng trang đã lưu
for page in pages_html:
tree = etree.HTML(page)
items = tree.xpath('//ul[@id="gzlist"]/li')
for item in items:
company = item.xpath('./dl/@title')[0] if item.xpath('./dl/@title') else ''
license_id = item.xpath('./ol/@title')[0] if item.xpath('./ol/@title') else ''
print(f"{company}: {license_id}")
driver.quit()
Sử dụng chuỗi hành động (Action Chains)
Khi cần mô phỏng các thao tác kéo thả (drag and drop), phải dùng lớp ActionChains. Đặc biệt chú ý nếu phần tử nằm trong iframe – cần chuyển ngữ cảnh trước:
from selenium import webdriver
from selenium.webdriver import ActionChains
import time
driver = webdriver.Chrome(executable_path='chromedriver.exe')
driver.get('https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
# Chuyển sang iframe chứa phần tử
driver.switch_to.frame('iframeResult')
draggable = driver.find_element_by_id('draggable')
actions = ActionChains(driver)
actions.click_and_hold(draggable)
# Di chuyển từng bước nhỏ
for _ in range(5):
actions.move_by_offset(15, 5).perform()
time.sleep(0.3)
actions.release() # Thả đối tượng
time.sleep(2)
driver.quit()
Chế độ vô hình (Headless Browser)
Để tăng hiệu suất và chạy ngầm, có thể kích hoạt chế độ headless – không hiển thị giao diện đồ họa:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
chrome_opts = Options()
chrome_opts.add_argument('--headless')
chrome_opts.add_argument('--disable-gpu')
chrome_opts.add_argument('--no-sandbox')
driver = webdriver.Chrome(executable_path='chromedriver.exe', options=chrome_opts)
driver.get('https://www.cnblogs.com')
print(driver.page_source)
driver.quit()
Thiết lập proxy mạng
Để ẩn địa chỉ IP hoặc truy cập qua máy chủ trung gian, có thể cấu hình proxy trong tùy chọn khởi động:
from selenium import webdriver
proxy_server = "113.74.61.232:28803"
options = webdriver.ChromeOptions()
options.add_argument(f'--proxy-server=http://{proxy_server}')
browser = webdriver.Chrome(executable_path='chromedriver.exe', options=options)
browser.get('https://httpbin.org/ip')
print(browser.page_source)
browser.quit()
Tránh bị phát hiện là bot
Một số website (như Taobao, Alibaba) có cơ chế phát hiện và chặn trình duyệt tự động. Để giảm khả năng bị phát hiện, có thể thêm các tùy chỉnh đặc biệt:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(executable_path='chromedriver.exe', options=options)
# Ngăn WebDriver thông báo rằng nó đang bị kiểm soát bởi phần mềm tự động
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
'source': '''
Object.defineProperty(navigator, 'webdriver', {
get: () => false
})
'''
})
driver.get('https://www.taobao.com')