Tại sao xác thực proxy trong Selenium lại khó?
Chrome nhận địa chỉ proxy thông qua đối số dòng lệnh --proxy-server, nhưng không nhận username và password trong địa chỉ đó. Khi kết nối với proxy yêu cầu username và password, trình duyệt sẽ hiển thị cửa sổ xác thực, và việc điền giá trị vào cửa sổ này bằng Selenium là khá khó khăn.
Giải pháp gọn nhất là IP authorization. Đăng ký IPv4 của server hoặc PC chạy Selenium vào dashboard, proxy sẽ chấp nhận kết nối từ IP đó mà không cần username/password. Chrome chỉ cần nhập ip:port. Tối đa 10 IP đăng ký để dùng chung trên nhiều server.
Ví dụ sử dụng IP 198.51.100.23, cổng HTTP 8000, cổng SOCKS5 1080.
pip install seleniumLàm thế nào để kết nối HTTP proxy với Chrome?
Sau khi đăng ký xác thực IP, thêm địa chỉ vào tham số --proxy-server trong ChromeOptions. Selenium 4.6+ có Selenium Manager tự động tải chromedriver phù hợp nên không cần cài đặt riêng.
Các tham số tương tự cũng được áp dụng trong chế độ headless. Để kiểm tra kết nối, hãy mở địa chỉ kiểm tra IP và xem IP hiển thị có phải là IP proxy hay không.
from selenium import webdriver
from selenium.webdriver.common.by import By
opts = webdriver.ChromeOptions()
opts.add_argument("--proxy-server=http://198.51.100.23:8000") # this machine's IP is authorized in the dashboard
opts.add_argument("--headless=new")
driver = webdriver.Chrome(options=opts)
try:
driver.get("https://api.ipify.org")
print(driver.find_element(By.TAG_NAME, "body").text) # should print the proxy IP
finally:
driver.quit()Làm thế nào để sử dụng SOCKS5 proxy trên Chrome?
Chỉ cần đặt địa chỉ socks5:// vào --proxy-server. Khi dùng SOCKS5, Chrome sẽ xử lý phân giải tên miền phía proxy, nhưng trong một số môi trường vẫn có thể còn DNS nội bộ, vì vậy nhiều người dùng thêm tham số --host-resolver-rules để chặn phân giải tên miền cục bộ.
SOCKS5 cũng kết nối bằng IP authorization vì Chrome không hỗ trợ xác thực bằng tên người dùng và mật khẩu cho proxy SOCKS.
from selenium import webdriver
opts = webdriver.ChromeOptions()
opts.add_argument("--proxy-server=socks5://198.51.100.23:1080")
# make sure host names are resolved through the proxy
opts.add_argument('--host-resolver-rules=MAP * ~NOTFOUND , EXCLUDE 198.51.100.23')
driver = webdriver.Chrome(options=opts)
driver.get("https://api.ipify.org")
print(driver.page_source)
driver.quit()Làm thế nào để kết nối với Firefox?
Firefox chỉ định proxy thông qua các giá trị cài đặt. Đặt network.proxy.type thành 1 (thủ công) và nhập địa chỉ HTTP hoặc SOCKS cùng với cổng. Đối với SOCKS5, đặt network.proxy.socks_version thành 5 và network.proxy.socks_remote_dns thành True để proxy phân giải tên miền.
Firefox cũng không có cách nào để nhập password proxy thông qua cài đặt dòng lệnh, vì vậy sử dụng IP authorization là cách đơn giản nhất.
from selenium import webdriver
opts = webdriver.FirefoxOptions()
opts.set_preference("network.proxy.type", 1)
opts.set_preference("network.proxy.socks", "198.51.100.23")
opts.set_preference("network.proxy.socks_port", 1080)
opts.set_preference("network.proxy.socks_version", 5)
opts.set_preference("network.proxy.socks_remote_dns", True)
driver = webdriver.Firefox(options=opts)
driver.get("https://api.ipify.org")
print(driver.page_source)
driver.quit()Làm thế nào để mở nhiều trình duyệt với các IP khác nhau cùng lúc?
Gán địa chỉ proxy khác nhau cho từng trình duyệt và chạy riêng lẻ. Ví dụ code sau nhận danh sách ip:port qua API rồi mở 3 trình duyệt với IP khác nhau. Do mỗi trình duyệt tốn nhiều bộ nhớ, hãy điều chỉnh số lượng đồng thời theo cấu hình server.
Để thực hiện các tác vụ sử dụng trình duyệt trong thời gian dài như phiên đăng nhập, bạn nên cố định một IP cho một trình duyệt và không thay đổi cho đến khi công việc hoàn tất.
import requests
from selenium import webdriver
KEY = "YOUR_API_KEY"
lines = requests.get(
"https://socks5proxy.io/api/v1/proxies/download",
params={"format": "ip:port", "protocol": "http"},
headers={"Authorization": "Bearer " + KEY},
timeout=30,
).text.split()
drivers = []
for line in lines[:3]:
opts = webdriver.ChromeOptions()
opts.add_argument("--headless=new")
opts.add_argument("--proxy-server=http://" + line)
drivers.append(webdriver.Chrome(options=opts))
for d in drivers:
d.get("https://api.ipify.org")
print(d.page_source)
d.quit()Nếu bắt buộc phải sử dụng xác thực bằng tên người dùng và mật khẩu thì làm thế nào?
Nếu không thể dùng xác thực IP, ví dụ môi trường có IP ra internet thay đổi liên tục, có hai cách. Một là dùng thư viện proxy trung gian như selenium-wire để chèn thông tin xác thực. Hai là chạy proxy trung gian local không xác thực trên cùng server, để Chrome kết nối qua địa chỉ local còn proxy local dùng username/password để kết nối tới Socks5Proxy.
Cả hai phương pháp đều làm tăng thành phần cần quản lý. Nếu có thể, sử dụng xác thực IP từ server có IP cố định là cách đơn giản và nhanh nhất.
Cần cài đặt gì để trình duyệt phù hợp với quốc gia đó?
Thay đổi tham số --lang của Chrome và cài đặt Accept-Language theo quốc gia IP để trang web mở bằng ngôn ngữ đó. Với trang nhạy cảm múi giờ, có thể dùng lệnh CDP Emulation.setTimezoneOverride để điều chỉnh.
Kích thước cửa sổ được đặt bằng đối số --window-size, và nếu bạn cần màn hình điện thoại, hãy sử dụng cài đặt giả lập thiết bị di động. Bạn có thể tạo các nhóm cài đặt theo quốc gia để chạy các thử nghiệm nhất quán trên nhiều quốc gia.
from selenium import webdriver
opts = webdriver.ChromeOptions()
opts.add_argument("--proxy-server=http://198.51.100.23:8000")
opts.add_argument("--lang=de-DE")
opts.add_argument("--window-size=1366,900")
driver = webdriver.Chrome(options=opts)
driver.execute_cdp_cmd("Emulation.setTimezoneOverride", {"timezoneId": "Europe/Berlin"})
driver.get("https://example.com/")
driver.quit()Có sử dụng cùng cài đặt trong Selenium Grid hoặc trình duyệt từ xa không?
Đúng vậy. ChromeOptions và FirefoxOptions vẫn hoạt động khi chạy từ xa. Thêm các tùy chọn tương tự vào webdriver.Remote để trình duyệt trên Grid node kết nối qua proxy. Lưu ý rằng IP cần đăng ký cho xác thực IP là IP của Grid node thực thi trình duyệt, không phải IP của máy tính chạy mã.
Nếu có nhiều node, hãy đăng ký tất cả IP của từng node. Bạn có thể đăng ký tối đa 10 IP. Nếu môi trường của bạn có node cloud thay đổi thường xuyên, việc gắn IP cố định vào node sẽ giúp quản lý dễ dàng hơn.
from selenium import webdriver
opts = webdriver.ChromeOptions()
opts.add_argument("--proxy-server=http://198.51.100.23:8000") # authorize the Grid node IP, not this machine
driver = webdriver.Remote(command_executor="http://grid.example.internal:4444", options=opts)
driver.get("https://api.ipify.org")
print(driver.page_source)
driver.quit()Cần kiểm tra những gì khi không thể kết nối?
ERR_PROXY_CONNECTION_FAILED thường xảy ra khi địa chỉ hoặc cổng không chính xác. Hãy đảm bảo bạn không nhập cổng SOCKS5 vào địa chỉ HTTP. Nếu bạn gặp ERR_TUNNEL_CONNECTION_FAILED hoặc cửa sổ xác thực xuất hiện, có thể IP đăng ký trong IP authorization khác với IP thực tế. Hãy kiểm tra IP của bạn bằng cách mở api.ipify.org trên máy chủ mà không sử dụng proxy và đăng ký giá trị đó.
IP gửi đi từ máy chủ đám mây có thể thay đổi sau khi khởi động lại. Hãy sử dụng IP cố định hoặc cập nhật danh sách IP cho phép trên bảng điều khiển khi IP thay đổi.