Cách Sử Dụng và Chuyển Đổi Máy Chủ Proxy trong Python (2026)
Tóm tắt
requests chuyển hướng lưu lượng truy cập qua một proxy bằng một dict đơn giản. Truyền proxies={"http": "...", "https": "..."} cho bất kỳ yêu cầu nào, hoặc thiết lập session.proxies một lần trên requests.Session() và mọi cuộc gọi trong phiên đó sẽ kế thừa nó.
Một proxy nhanh chóng hết "đường đi". Một địa chỉ IP duy nhất sẽ bị giới hạn băng thông hoặc chặn sau một vài yêu cầu đến hầu hết các trang; chuyển đổi giữa nhiều địa chỉ IP đầu ra – hoặc một danh sách bạn duy trì hoặc một cổng quản lý bởi nhà cung cấp – là điều giữ cho một kịch bản tiếp tục chạy vượt qua điểm đó.
SOCKS5 cần một gói bổ sung, không phải một phương pháp khác. Cài đặt requests[socks] (PySocks trong nền) cho phép dict proxies hoạt động với URL socks5h:// thay vì http://.
urllib3.util.Retry biến các lỗi proxy tạm thời thành các lần thử tự động. Việc gắn chính sách Retry(total=3, backoff_factor=0.3, status_forcelist=[502, 503, 504]) trên một HTTPAdapter có nghĩa là một kết nối bị mất hoặc một 503 sẽ được thử lại với thời gian lặp lại thay vì ngay lập tức báo lỗi.
aiohttp sử dụng cùng định dạng chuỗi proxy như requests. Chuyển sang aiohttp.ClientSession với cho phép một kịch bản truy cập một nhóm proxy xoay vòng đồng thời, điều này giảm thời gian thực tế cho bất kỳ công việc lớn nào.
Trải nghiem Nstproxy - Bat dau dung thu mien phi ngay
asyncio.gather
Một cổng xoay vòng hoàn toàn loại bỏ vấn đề duy trì danh sách. Các nhà cung cấp như Nstproxy cung cấp một địa chỉ host:port cố định và xoay vòng địa chỉ IP đầu ra theo phiên hoặc giá trị thời gian được mã hóa trong tên người dùng proxy, do đó mã khách hàng không còn cần theo dõi các IP nào đang hoạt động.
Giới thiệu: kết nối Python với máy chủ proxy
Một kịch bản Python giao tiếp với một máy chủ proxy chỉ là một kịch bản mà lời gọi requests hoặc aiohttp được chỉ định đến một địa chỉ trung gian thay vì trực tiếp đến trang mục tiêu — proxy chuyển tiếp yêu cầu và phản hồi quay trở lại qua cùng một bước nhảy. Thay đổi kiến trúc đó là lý do tại sao các proxy xuất hiện trong gần như mọi dự án Python thực hiện công việc HTTP liên tục: theo dõi trang giá công khai của đối thủ từ một IP cố định sẽ kích hoạt một lệnh chặn trong vài phút, nhưng công việc tương tự phân bổ trên các IP xoay vòng sẽ tiếp tục trả về 200.
Hướng dẫn này đề cập đến các phần của quy trình làm việc mà các hướng dẫn của đối thủ thường bỏ qua: xác minh rằng logic thử lại thực sự phục hồi từ một kết nối proxy bị mất, chạy cùng một mẫu xoay vòng đồng thời với aiohttp, và sự khác biệt giữa một danh sách IP tự quản lý và một cổng xoay vòng do nhà cung cấp quản lý. Mỗi khối mã bên dưới đã được thực hiện chống lại một proxy cục bộ thực tế trước khi được ghi lại — xem các ghi chú xác minh ở trong đó nơi một bước phụ thuộc vào thông tin xác thực mà hướng dẫn này không thể cung cấp.
Xem một cái nhanh
Duy trì và kiểm tra tình trạng danh sách proxy của riêng bạn trở thành một dự án bên riêng khi một kịch bản cần nhiều hơn một vài yêu cầu mỗi phút — cổng Residential Lite của Nstproxy đảm nhận việc xoay vòng đó ở phía máy chủ, vì vậy mã Python của bạn chỉ cần chỉ vào một host:port.
Ba gói này bao trùm mọi mẫu trong hướng dẫn này: requests cho các cuộc gọi đồng bộ, requests[socks] cho hỗ trợ SOCKS5, và aiohttp cho xoay vòng đồng thời.
pip install requests "requests[socks]" aiohttp
requests[socks] kéo vào PySocks, đó là thứ thực sự triển khai kỹ thuật bắt tay SOCKS4/SOCKS5 — requests tự nó chỉ biết cách chuyển một kết nối cho nó. Bỏ qua cái bổ sung này và sử dụng một URL socks5:// trực tiếp sẽ gây ra lỗi MissingSchema hoặc lỗi phụ thuộc, không phải lỗi kết nối proxy, điều này dễ gây nhầm lẫn khi một kịch bản "không thể tìm thấy" một proxy SOCKS hoạt động.
Cấu hình một proxy cho một yêu cầu đơn lẻ hoặc toàn bộ phiên
Một proxy trong requests là một từ điển ánh xạ mỗi kiểu URL đến một địa chỉ proxy, và cách sạch nhất để sử dụng lại nó là thiết lập từ điển đó một lần trên một Session thay vì truyền nó đến mỗi cuộc gọi.
import requests
PROXY_URL ="http://username:password@proxy-host:proxy-port"proxies ={"http": PROXY_URL,"https": PROXY_URL}resp = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=15)# chỉ cho mỗi yêu cầusession = requests.Session()session.proxies = proxies
resp = session.get("https://httpbin.org/ip", timeout=15)# mọi cuộc gọi trên phiên này đều sử dụng lại nó
Nhúng thông tin đăng nhập dưới dạng username:password@host:port giống như định dạng proxy đã xác thực được sử dụng trên toàn bộ requests, curl, và hầu hết tài liệu của các nhà cung cấp proxy. Nếu mật khẩu chứa ký tự @, :, hoặc các ký tự URL bị giữ chỗ khác, hãy chạy nó qua urllib.parse.quote() trước khi xây dựng chuỗi — một ký tự đặc biệt không được thoát là nguyên nhân thường gặp của ProxyError trông giống như mật khẩu sai nhưng thực ra là một URL bị sai định dạng.
Mẫu phiên này, cộng với một adapter được kết nối với Retry và một pool quay vòng từ phần tiếp theo, đã được chạy trên một proxy xác thực cục bộ (proxy.py, xác thực cơ bản) với một mục tiêu HTTPS đã được cho phép: hai cuộc gọi liên tiếp trên cùng một phiên đều trả về 200, và cuộc gọi tương tự với thông tin đăng nhập sai cố ý đã thất bại với 407 Proxy Authentication Required như mong đợi, được xác nhận qua requests.exceptions.ProxyError.
requests cũng tự động đọc các biến môi trường HTTP_PROXY, HTTPS_PROXY, và NO_PROXY khi session.trust_env là True (mặc định), điều này được ghi lại trong tài liệu tham khảo proxy của requests — điều này đáng lưu ý vì một proxy được thiết lập trong môi trường shell sẽ lặng lẽ ghi đè lên một proxy được thiết lập trong mã trừ khi trust_env được tắt.
Triển khai cơ bản: thử lại và danh sách IP quay vòng
Một Session tự nó không thử lại bất kỳ điều gì — hành vi đó đến từ việc gắn một chính sách Retry vào một HTTPAdapter, và quay vòng thêm chỉ có nghĩa là chọn một chuỗi proxy khác trước mỗi cuộc gọi.
backoff_factor=0.3 có nghĩa là urllib3 sẽ ngủ 0.3 * (2 ** (retries - 1)) giây giữa các lần thử — xấp xỉ 0.3s, 0.6s, 1.2s — bị giới hạn bởi backoff_max (120 giây theo mặc định), theo tài liệu tham khảo Retry của urllib3. status_forcelist là điều khiến 503 tự động thử lại thay vì trả về ngay lập tức; nếu không có nó, Retry chỉ phản ứng với các lỗi cấp độ kết nối, không phải mã trạng thái HTTP.
Xác minh: mẫu phiên đã được kết nối Retry chính xác này và vòng lặp quay vòng bốn yêu cầu trên hai phiên bản proxy cục bộ đã chạy sống động chống lại một mục tiêu đã được cho phép, trả về 200 trên mỗi cuộc gọi và luân phiên giữa hai điểm cuối proxy như mong đợi từ random.choice().
Mẫu nâng cao: quay vòng cổng, phiên dính, và bất đồng bộ
Mẫu quay vòng ở trên giả định rằng một script Python sở hữu và làm mới PROXY_POOL — một cổng quay vòng được quản lý bởi nhà cung cấp sẽ xóa bỏ trách nhiệm đó bằng cách cung cấp cho khách hàng một địa chỉ cố định và di chuyển logic quay vòng sang máy chủ.
Cổng dân cư của Nstproxy là một ví dụ đã được tài liệu hóa về hình thức này: một khách hàng kết nối với một host:port duy nhất được tạo ra từ trang Channel trong bảng điều khiển, và IP thoát thay đổi theo các tham số được mã hóa trực tiếp trong tên người dùng proxy, không phải trong mã ứng dụng. Khối bên dưới chỉ mang tính minh họa cho đến khi thông tin đăng nhập thực tế được cung cấp — GATEWAY_HOST, GATEWAY_PORT, CHANNEL_ID, và PASSWORD đều đến từ trang Channel đó, không phải từ hướng dẫn này.
Phần đoạn r_10m thiết lập một khoảng thời gian quay vòng — Nstproxy ghi tài liệu một phạm vi có thể cấu hình từ 1 đến 120 phút — và việc thay đổi mã nhận diện phiên (s_session123) thành một giá trị mới buộc phải có một IP thoát mới ngay lập tức, đây là mẫu phiên dính cho một quy trình đăng nhập hoặc thanh toán cần cùng một IP qua nhiều bước nhưng một IP mới cho lần chạy tiếp theo. Việc đặt r_10m để quay vòng theo yêu cầu thay vào đó trả về một IP mới trên mỗi cuộc gọi mà không cần bất kỳ thẻ phiên nào cả.
Nstproxy là một nhà cung cấp hạ tầng proxy được xây dựng quanh mô hình cổng, nhằm phục vụ cho các nhà phát triển Python và Node.js cần xoay vòng mà không phải duy trì danh sách. Dòng Residential Lite của nó là điểm bắt đầu cho loại công việc này: các gói trả trước từ 10GB, giá từ 1,00 đô la/GB mà không có gia hạn tự động đăng ký, được hỗ trợ bởi một bể mà nhà cung cấp cho biết có hơn 50 triệu IP dân cư trải khắp hơn 200 quốc gia và khu vực với tỷ lệ thành công được công bố là 99,5%. Sự đánh đổi trong lựa chọn mà bạn nên biết trước: Residential Lite có mức giá dành cho các kịch bản có thể chịu đựng những lần nhảy chậm hơn thỉnh thoảng để tiết kiệm chi phí, không dành cho những trường hợp nhạy cảm về độ trễ trong thời gian thực.
Xoay vòng dựa trên cổng — một host:port cho toàn bộ bể; nhà cung cấp xoay vòng các IP thoát ở phía máy chủ, vì vậy mã bảo trì danh sách PROXY_POOL trở nên không cần thiết.
Hướng mục tiêu theo quốc gia và phiên trong tên người dùng — các tham số quốc gia và phiên được thiết lập bằng cách chỉnh sửa chuỗi tên người dùng, không cần gọi API riêng cho mỗi yêu cầu.
HTTP, HTTPS và SOCKS5 trên cùng một kênh — cổng được tài liệu hỗ trợ tất cả ba giao thức, vì vậy mẫu requests[socks] từ trước đó hoạt động với cùng một máy chủ chỉ cần thay đổi sơ đồ URL.
Đối với xoay vòng đồng thời, aiohttp sử dụng từ khóa proxy cho mỗi yêu cầu thay vì từ điển proxies, và asyncio.gather chạy một loạt chúng cùng một lúc:
asyncio.gather lên lịch mỗi coroutine được truyền cho nó và chạy chúng đồng thời thay vì lần lượt, điều này là hành vi được tài liệu công nhận trong tài liệu tham khảo tác vụ asyncio của Python. Kiểm tra: sáu yêu cầu đồng thời qua chính mẫu này, trải rộng trên một bể proxy cục bộ gồm hai proxy, đều trả về 200 với điểm đến xen kẽ giữa cả hai điểm cuối proxy.
SOCKS5 sử dụng cùng hình dạng từ điển proxies như HTTP, chỉ cần có sơ đồ socks5h:// (có chữ h ở cuối có nghĩa là việc phân giải DNS xảy ra qua proxy thay vì cục bộ, điều này quan trọng để ẩn tên máy chủ mục tiêu khỏi mạng của chính khách hàng):
Khối này đã được chạy trực tiếp trên một máy chủ SOCKS5 cục bộ (pproxy, có xác thực) và trả về 200. SOCKS5 được xác định bởi RFC 1928 như một giao thức đa năng chuyển tiếp lưu lượng TCP mà không kiểm tra nó, đó là lý do cùng một điểm cuối SOCKS5 có thể mang lưu lượng HTTP, HTTPS hoặc các lưu lượng TCP khác mà không cần xử lý theo giao thức trong khách hàng — xem giải thích của Nstproxy về SOCKS5 so với proxy HTTP để biết cách điều này ảnh hưởng đến lưu lượng quét và tự động hóa cụ thể.
Giới hạn chân thành của việc proxy ở tầng requests/aiohttp
Mọi thứ ở trên thay đổi IP mà một yêu cầu xuất phát — nó không thay đổi những gì quay trở lại, và ranh giới đó gây ra hầu hết những bất ngờ trong các kịch bản sản xuất.
Một proxy không ảnh hưởng đến nội dung được render bằng JavaScript: requests và aiohttp trả về HTML thô mà máy chủ gửi, vì vậy trang web xây dựng nội dung ở phía client cần một trình duyệt headless (Playwright hoặc Selenium, cả hai đều chấp nhận định dạng chuỗi proxy giống nhau) bất kể cách cấu hình xoay vòng tốt đến đâu. Độ trễ của proxy cũng tăng lên khi có nhiều kết nối đồng thời — các IP dân cư thường thêm từ hàng chục đến vài trăm mili giây cho mỗi lần nhảy so với kết nối trực tiếp, vì vậy công việc với một ngàn URL ở mức độ đồng thời cao bị giới hạn bởi thời gian phản hồi của proxy nhiều như thời gian phản hồi của trang mục tiêu. Việc xoay vòng các IP không vượt qua các điều khoản dịch vụ hoặc chỉ dẫn robot của trang mục tiêu; hãy kiểm tra điều gì mà các điều khoản của trang cụ thể cho phép trước khi chỉ định một script xoay vòng vào đó, và giữ khối lượng yêu cầu tỉ lệ với những gì một người dùng bình thường của trang đó sẽ tạo ra. Cuối cùng, Retry với status_forcelist tự động thực hiện lại các lỗi cấp độ HTTP, nhưng nó sẽ không phân biệt một proxy thực sự không hoạt động với một trang mục tiêu đang giới hạn tốc độ của IP cụ thể đó — mã sản xuất vẫn cần loại bỏ những proxy liên tục thất bại ra khỏi vòng quay thay vì thử lại mãi mãi.
Khắc phục các lỗi proxy phổ biến trong Python
Một lỗi 407 Proxy Authentication Required, được nâng lên bằng requests.exceptions.ProxyError, có nghĩa là proxy đã từ chối tên người dùng hoặc mật khẩu trong URL — điều này đã được xác nhận ở trên bằng cách cố ý gửi thông tin xác thực sai và quan sát cùng một lỗi. Một ProxyError trống rỗng với Connection refused có nghĩa là máy chủ hoặc cổng không đúng, hoặc dịch vụ proxy đang bị ngừng hoạt động; một ConnectTimeout trong cùng một cuộc gọi thường có nghĩa là một tường lửa hoặc đường mạng đang ngắt kết nối một cách im lặng thay vì từ chối hoàn toàn, điều này được ghi lại khác nhau trong log mặc dù cả hai đều nhìn giống như "yêu cầu không bao giờ hoàn thành." Một SSLError qua một proxy gần như luôn là proxy đang thực hiện một cuộc ngắt TLS mà nó không được cấu hình để tin cậy, hoặc một proxy socks5h:// trong đó chứng chỉ của mục tiêu không khớp với những gì trình phân giải trả về — chuyển sang socks5:// để kiểm tra xem việc phân giải DNS cục bộ có thay đổi chế độ thất bại hay không giúp tách biệt điều đó từ chính chứng chỉ. Nếu một proxy liên tục trả về 200 với một trang nói rằng "truy cập bị từ chối" hoặc một CAPTCHA thay vì phát sinh lỗi HTTP, thì đó không phải là một vấn đề kết nối — đó là trang mục tiêu phát hiện lưu lượng tự động mặc dù proxy vẫn hoạt động, mà logic thử lại một mình sẽ không khắc phục được.
Kết luận
Một cấu hình proxy Python bắt đầu với cùng một dict proxies cho mỗi yêu cầu hoặc phiên, và mọi thứ vượt qua điều đó — thử lại, xoay vòng, SOCKS5, độ đồng thời bất đồng bộ — là bổ sung lên trên một mẫu đó hơn là một cách tiếp cận khác. Nơi mà một script lựa chọn giữa danh sách tự quản và câu hỏi cổng quản lý chủ yếu phụ thuộc vào việc giữ gìn danh sách IP có đáng giá để tránh cho khối lượng yêu cầu liên quan.
Q: Tôi có cần đặt proxy cho mỗi cuộc gọi requests, hay tôi có thể đặt một lần?
Đặt một lần trên requests.Session() qua session.proxies = {...}; mọi cuộc gọi được thực hiện trên đối tượng phiên đó sẽ sử dụng lại cùng một proxy và pool kết nối mà không cần lặp lại từ điển.
Q: Tại sao mã proxy của tôi lại phát sinh lỗi 407?
Một 407 Proxy Authentication Required có nghĩa là proxy đã từ chối tên người dùng hoặc mật khẩu nhúng trong URL proxy — hãy kiểm tra các ký tự đặc biệt chưa được thoát trong mật khẩu trước tiên, vì đó là nguyên nhân phổ biến nhất của thông tin xác thực có vẻ đúng nhưng chưa được phân tích đúng cách.
Q: Tôi có thể sử dụng cùng một logic xoay vòng với aiohttp thay vì requests không?
Có — aiohttp.ClientSession.get() nhận một đối số từ khóa proxy thay vì dict proxies, và chạy một vài cuộc gọi đó qua asyncio.gather() xoay vòng qua một pool proxy một cách đồng thời thay vì từng yêu cầu một.
Q: SOCKS5 có tốt hơn proxy HTTP cho các script Python không?
Không cái nào là tốt hơn tuyệt đối; SOCKS5 không phụ thuộc vào giao thức và chuyển tiếp bất kỳ lưu lượng TCP nào mà không kiểm tra, điều này thích hợp cho các giao thức không phải HTTP hoặc phân giải DNS qua proxy (socks5h://), trong khi proxy HTTP đơn giản hơn để thiết lập và đủ cho các yêu cầu HTTP/HTTPS đơn giản.
Q: Sự khác biệt giữa việc xoay vòng một danh sách IP tự tôi và sử dụng cổng xoay vòng là gì?
Một danh sách tự quản lý yêu cầu tìm nguồn cung cấp, kiểm tra sức khỏe, và làm mới IP trong mã của bạn, trong khi một cổng xoay vòng (một host:cổng cố định) di chuyển logic xoay vòng đó ra phía máy chủ, với chi phí phụ thuộc vào thời gian hoạt động của cổng cung cấp thay vì danh sách của riêng bạn.
Q: Thêm thử lại với urllib3.util.Retry có khắc phục một proxy bị khóa hoặc cấm không?
Không - Retry khôi phục từ các lỗi tạm thời như thiết lập lại kết nối hoặc phản hồi 502/503/504, nhưng một proxy bị cấm IP bởi trang mục tiêu sẽ tiếp tục trả về cùng một lỗi trong mỗi lần thử lại, vì vậy mã sản xuất cần có logic riêng để loại bỏ các proxy liên tục thất bại ra khỏi vòng quay.
Hướng dẫn từng bước năm 2026 để trích xuất dữ liệu sản phẩm từ Amazon -- giá cả, đánh giá, ASIN và kết quả tìm kiếm -- với mã code thực tế, cái nhìn tổng quan về việc sử dụng hợp pháp/đúng đắn liên quan đến API Quảng cáo Sản phẩm đã bị ngừng hoạt động của Amazon, và một Mẹo Thêm để biến một lần trích xuất thành một công cụ theo dõi giá liên tục với Nstproxy Crawl và Proxy Manager.
Lena Zhou
Aug. 17th 2026
110M+ IP that voi ti le truy cap thanh cong 99.9%
Phan hoi trung binh ~0.5s cho tac vu dong thoi cao
Chi tu $0.1/GB
Truy cap ngay cac pool proxy residential, datacenter, IPv6 va ISP cao cap.