Cách xoay vòng proxy trong Python: Hướng dẫn đầy đủ 2026
Tóm tắt
Quay vòng proxy trong Python có nghĩa là chọn một URL proxy khác từ danh sách trong mỗi yêu cầu, không phải là chế độ đặc biệt của thư viện requests.requests chỉ biết cách sử dụng bất kỳ từ điển proxy nào bạn cung cấp cho cuộc gọi đó; mã của bạn quyết định proxy nào sẽ được sử dụng.
Một từ điển proxies được khóa theo scheme ({"http": ..., "https": ...}) là định dạng duy nhất mà requests chấp nhận, và nó có thể được truyền theo từng yêu cầu hoặc thiết lập một lần trên một Session. Theo từng yêu cầu là an toàn hơn cho việc quay vòng, vì việc cập nhật session.proxies trong mỗi vòng lặp rất dễ bị sai.
Các biến môi trường âm thầm ghi đè session.proxies. Tài liệu của requests cảnh báo rằng HTTP_PROXY/HTTPS_PROXY trong môi trường có ưu tiên hơn bất kỳ điều gì bạn thiết lập trên một phiên, và bài viết này tái hiện việc ghi đè đó trong thời gian thực để bạn có thể thấy nó xảy ra.
itertools.cycle cung cấp cho bạn quay vòng theo kiểu round-robin chỉ với ba dòng mã, nhưng nó không biết khi nào một proxy không hoạt động. Quay vòng trong sản xuất cần một vòng lặp thử lại và bỏ qua xung quanh nó, mà bài viết này xây dựng và thực hiện với một lỗi proxy thực tế.
Lớp Retry của urllib3 thử lại cùng một kết nối; nó không quay vòng giữa các proxy khác nhau. Nhầm lẫn giữa hai điều này là lý do phổ biến khiến mã quay vòng "dường như không quay vòng" — và quay vòng proxy giải quyết những vấn đề khác nhau và thường bạn cần cả hai.
Trải nghiem Nstproxy - Bat dau dung thu mien phi ngay
Retry
Quay vòng URL proxy là độc lập với nguồn gốc của những URL đó. Vòng lặp giống nhau hoạt động cho dù danh sách là ba địa chỉ IP mà bạn đã hardcode cho việc kiểm tra hay một nhóm lớn từ nhà cung cấp trả phí; mã trong bài viết này đã được xác nhận với các máy chủ thử nghiệm cục bộ chính xác để nó không phụ thuộc vào bất kỳ nhà cung cấp nào.
"Quay vòng proxy" thực sự có nghĩa gì trong một kịch bản
Quay vòng proxy có nghĩa là gửi các yêu cầu khác nhau qua các máy chủ proxy khác nhau để không có IP đầu ra nào xử lý mọi yêu cầu. Không có gì trong Python hoặc requests tự động quay vòng — requests.get(url, proxies=proxy_dict) gửi chính xác một yêu cầu qua chính xác một proxy, và vòng lặp của bạn quyết định proxy_dict nào sẽ truyền trong cuộc gọi tiếp theo. Sự phân biệt này quan trọng vì nhiều lỗi quay vòng hóa ra là "vòng lặp không bao giờ thực sự thay đổi từ điển" hơn là vấn đề với proxy. Phần còn lại của bài viết này xây dựng vòng lặp từ một proxy đã được hard-code đến một nhóm an toàn với tự động chuyển tiếp, thực hiện mọi ví dụ trên các máy chủ cục bộ thực tế để bạn có thể thấy hành vi thực tế thay vì chỉ tin vào một đoạn mã.
Cài đặt những gì bạn cần
Bạn cần thư viện requests, vốn kéo theo urllib3 như một phụ thuộc và xử lý cả proxy HTTP thông thường và, kể từ requests 2.10+, các proxy SOCKS nếu bạn cũng cài đặt phần mở rộng socks:
pip install requests
pip install"requests[socks]"# chỉ cần thiết cho các URL proxy socks5://
Không cần gói nào khác cho các mẫu trong bài viết này — quay vòng chỉ là một vài chục dòng mã thư viện tiêu chuẩn (itertools, random, threading, concurrent.futures) cộng với requests chính nó.
Cấu hình một proxy đơn trước khi bạn quay vòng
Trả lời tiêu đề một cách trực tiếp: requests mong đợi một từ điển với các khóa "http" và "https", mỗi khóa trỏ đến một URL proxy, và bạn có thể truyền từ điển này đến một cuộc gọi cá nhân hoặc gắn nó vào một Session. Tài liệu của requests cho thấy hình thức theo từng yêu cầu như sau:
và hình thức theo từng Session là session.proxies.update(proxies) tiếp theo là session.get(...). Thông tin xác thực đi thẳng vào URL dưới dạng http://user:pass@host:port. Tài liệu cùng nhấn mạnh một điều cần biết trước khi bạn xây dựng bất kỳ điều gì dựa trên điều này: nó nêu rõ rằng "các giá trị được cung cấp sẽ bị ghi đè bởi các proxy môi trường," có nghĩa là một biến môi trường HTTP_PROXY hoặc HTTPS_PROXY sẽ có ưu tiên hơn bất kỳ điều gì bạn đã thiết lập trên session.proxies. Điều này rất thực tế và dễ gặp phải — chạy đoạn mã sau trên một máy (hoặc trình chạy CI) với HTTP_PROXY đã được xuất trước đó sẽ tái hiện điều này:
import os
import requests
os.environ["HTTP_PROXY"]="http://127.0.0.1:8002"session = requests.Session()session.proxies.update({"http":"http://127.0.0.1:8001"})resp = session.get("http://internal.test/", timeout=5)print(resp.json()["served_by"])
proxy-2
Phiên đã được chỉ định sử dụng proxy trên cổng 8001; biến môi trường đã thắng, và mọi yêu cầu trong phiên đã đi qua cổng 8002 thay vì. Nếu mã quay vòng của bạn là một Session và nó dường như đang bỏ qua danh sách proxy của bạn, hãy kiểm tra các biến môi trường của bạn trước khi kiểm tra logic quay vòng của bạn.
Nhìn nhanh
```html
Việc kiểm tra logic xoay vòng trên ba máy chủ cục bộ chứng minh rằng vòng lặp hoạt động, nhưng điều đó sẽ không cho bạn biết cách mà các proxy thực tế hoạt động dưới tải — cổng vào của Nstproxy cung cấp cho bạn một tập hợp lớn IP thực để chỉ đến cùng một mã khi bạn đã sẵn sàng.
Vòng lặp xoay vòng đơn giản nhất sẽ xoay quanh một danh sách cố định các URL proxy và cung cấp một cái mới cho requests mỗi lần gọi. Ví dụ này được chạy trên ba máy chủ HTTP cục bộ khởi động trên các cổng 8001–8003 cho bài viết này, mỗi máy chủ xác định bản thân mình trong phản hồi của nó để vòng xoay là có thể xác minh thay vì giả định:
import itertools
import requests
PROXIES =["http://127.0.0.1:8001","http://127.0.0.1:8002","http://127.0.0.1:8003",]proxy_cycle = itertools.cycle(PROXIES)for i inrange(6): proxy =next(proxy_cycle) resp = requests.get("http://internal.test/products", proxies={"http": proxy,"https": proxy}, timeout=5,)print(f"yêu cầu {i +1}: gửi qua {proxy} -> {resp.json()['served_by']}")
Đầu ra thực tế từ lần chạy đó:
yêu cầu 1: gửi qua http://127.0.0.1:8001 -> proxy-1
yêu cầu 2: gửi qua http://127.0.0.1:8002 -> proxy-2
yêu cầu 3: gửi qua http://127.0.0.1:8003 -> proxy-3
yêu cầu 4: gửi qua http://127.0.0.1:8001 -> proxy-1
yêu cầu 5: gửi qua http://127.0.0.1:8002 -> proxy-2
yêu cầu 6: gửi qua http://127.0.0.1:8003 -> proxy-3
itertools.cycle là toàn bộ mẹo: nó là một bộ lặp vô hạn quay trở lại bắt đầu danh sách mãi mãi, vì vậy next(proxy_cycle) luôn trả về một proxy mà không cần bạn theo dõi một chỉ số. Thay đổi PROXIES bằng các URL proxy thực và vòng lặp hoạt động chính xác theo cách tương tự — nó không biết liệu danh sách đó có đến từ ba máy chủ thử nghiệm cục bộ hay một hồ bơi thương mại, điều đó là lý do tại sao việc thử nghiệm theo cách này trước tiên là ý kiến hay.
Mẫu nâng cao: Chuyển đổi và Xoay đồng thời
Xoay vòng theo kiểu round-robin một mình không trả lời câu hỏi mà mọi kịch bản xoay vòng cuối cùng phải có: điều gì xảy ra khi một trong các proxy đang down? Mẫu bên dưới chọn một proxy ngẫu nhiên từ hồ bơi, bắt các ngoại lệ cụ thể mà requests thông báo cho các lỗi proxy và kết nối, và chuyển sang ứng viên tiếp theo thay vì để toàn bộ yêu cầu thất bại:
ProxyError được tài liệu hóa như một lớp con của ConnectionError được nâng lên đặc biệt cho các lỗi liên quan đến proxy, đó là lý do tại sao nó được bắt cùng với ConnectionError và Timeout chung hơn. Chạy điều này trên một hồ bơi gồm bốn địa chỉ — ba máy chủ cục bộ thực và một cổng không có gì lắng nghe — đã sản xuất như sau trong một lần chạy:
cố gắng 1: http://127.0.0.1:8004 thất bại (ProxyError), xoay vòng
thành công qua http://127.0.0.1:8003 -> proxy-3
Địa chỉ chết đã thất bại ngay lập tức và vòng lặp đã chuyển sang mà không làm hỏng kịch bản. Bởi vì random.shuffle sắp xếp lại hồ bơi mỗi lần gọi, một lần chạy khác có thể thành công ngay từ nỗ lực đầu tiên nếu bước xáo trộn đưa một proxy hoạt động lên trước — cả hai kết quả đều là hành vi đúng cho mẫu này.
Xoay vòng từ nhiều luồng thêm một yêu cầu nữa: bất cứ thứ gì chọn "proxy tiếp theo" phải an toàn để gọi từ nhiều luồng cùng một lúc. Một itertools.cycle chia sẻ phía sau một threading.Lock, được điều khiển bởi ThreadPoolExecutor, giữ cho thứ tự round-robin không bị ảnh hưởng dưới sự đồng thời:
đường dẫn = [f"/item/{i}" cho i trong phạm vi(9)]
với ThreadPoolExecutor(max_workers=4) làm hồ bơi:
tương lai = [hồ bơi.submit(fetch, p) cho p trong đường dẫn]
cho tương lai trong as_completed(tương lai):
in(tương lai.result())
Chín yêu cầu qua bốn luồng công nhân vẫn rơi đúng ba yêu cầu cho mỗi proxy, theo thứ tự, vì khóa sẽ tuần tự hóa quyền truy cập vào bộ lặp chia sẻ mặc dù các yêu cầu thực tế chạy đồng thời. ThreadPoolExecutor là một phần của mô-đun concurrent.futures trong thư viện tiêu chuẩn — không cần phụ thuộc bổ sung cho mẫu này.
Giới Hạn Trung thực: Điều Gì Mà Mã Quay Này Không Thể Khắc Phục
Mã này quyết định URL proxy nào sẽ được sử dụng cho mỗi yêu cầu; nó không có ý kiến về nơi các URL đó đến từ đâu hoặc liệu chúng có tốt hay không. Một danh sách ba địa chỉ IP chết sẽ quay qua một cách mượt mà như một danh sách ba địa chỉ IP khỏe mạnh — vòng lặp khôi phục ở trên chỉ chứng minh rằng nó có thể khôi phục từ một số proxy xấu, không phải danh sách cụ thể của bạn có thể sử dụng được.
Retry từ urllib3 không phải là sự thay thế cho logic quay trong bài viết này. Các tham số của nó — tổng, hệ số_nhảy_lùi, danh_sách_trạng_thái_bắt_buộc — mô tả việc thử lại cùng một yêu cầu với cùng một kết nối với độ trễ nhảy lùi giữa các lần thử; không có gì trong urllib3.util.Retry chuyển sang một proxy khác. Nếu bạn gán một HTTPAdapter được cấu hình Retry trên một phiên có một proxy được thiết lập, mỗi lần thử lại vẫn đi qua cùng một proxy đó. Quay sang một proxy khác khi gặp lỗi là điều mà hàm get_with_rotation ở trên thực hiện thay vào đó, và hai kỹ thuật này nên được kết hợp, không phải chọn giữa chúng.
Không ví dụ nào ở đây xử lý các giới hạn về tỷ lệ xác thực proxy, ngữ nghĩa phiên kết dính, hoặc định tuyến theo quốc gia — đó là thuộc tính của bất kỳ dịch vụ proxy nào đứng sau các URL, không phải điều mà itertools.cycle hoặc một vòng lặp thử lại có thể thêm vào.
Khắc Phục Các Lỗi Quay Thông Thường
requests.exceptions.ProxyError có nghĩa là kết nối tới proxy đã thất bại — proxy bị chết, cổng sai, hoặc tường lửa đang chặn nó. Đây là điều mà cổng chết trong ví dụ khôi phục ở trên kích hoạt.
requests.exceptions.ConnectionError mà không có kiểu phụ ProxyError cụ thể hơn thường có nghĩa là proxy đã chấp nhận kết nối nhưng không thể đến được trang đích, điều này thường xuất hiện như một proxy gần đến cuối tuổi thọ có thể sử dụng nếu bạn đang lấy từ một nhóm quay.
Quay dường như không xảy ra mặc dù vòng lặp của bạn nhìn đúng — hãy kiểm tra biến môi trường HTTP_PROXY hoặc HTTPS_PROXY trước tiên, theo cách tái sản xuất trực tiếp trước đó trong bài viết này; nó sẽ im lặng ghi đè session.proxies và khiến mỗi yêu cầu đi qua cùng một địa chỉ bất kể vòng lặp của bạn đã chọn điều gì.
Mỗi yêu cầu đều hết thời gian ở cùng một giá trị timeout thay vì thất bại nhanh trên các proxy chết — hãy giảm tham số timeout đặc biệt cho việc kiểm tra sức khỏe của một nhóm mới, vì một giá trị timeout rộng rãi dành cho các yêu cầu thực tế sẽ khiến một proxy chết treo trong suốt khoảng thời gian đó trong mỗi lần thử quay.
Chỉ Mã Quay Vào Một Nhóm Proxy Thực Sự
Các vòng lặp trong bài viết này quay qua bất kỳ danh sách nào bạn cung cấp cho chúng, và việc thay thế bằng một cổng thương mại đồng nghĩa với việc thay đổi danh sách, không thay đổi logic. Nstproxy là một nhà cung cấp hạ tầng proxy cung cấp các nhóm IP dân cư, trung tâm dữ liệu, ISP tĩnh, IPv6 và di động, có thể truy cập qua HTTP, HTTPS hoặc SOCKS5 thông qua một cổng duy nhất thay vì một danh sách các IP cá nhân mà bạn tự quản lý. Trang sản phẩm Residential Lite Proxies của nó tài liệu hóa mẫu kết nối trực tiếp: một cổng host và cổng cố định, với việc quay IP thực sự xảy ra sau một địa chỉ duy nhất trên phía nhà cung cấp thay vì trong danh sách Python của bạn — xem tài liệu của Nstproxy để biết host, cổng và thông số xác thực hiện tại trước khi kết nối chúng vào các ví dụ ở trên. Điều đó phù hợp với các nhóm muốn hành vi quay từ bài viết này mà không cần duy trì và kiểm tra sức khỏe danh sách IP proxy cá nhân của riêng họ. Sự đánh đổi là bạn đang tin tưởng vào hành vi quay của nhà cung cấp phía sau cổng thay vì kiểm soát trực tiếp nó như cách mà các ví dụ itertools.cycle và khôi phục ở trên thực hiện.
Một cổng host thay vì một danh sách để duy trì — mã từ ví dụ cơ bản của bài viết này thu gọn thành một từ điển proxy duy nhất chỉ vào địa chỉ cổng đó thay vì một danh sách nhiều cái; hãy kiểm tra liên kết tài liệu ở trên để biết host và cổng hiện tại chính xác trước khi sử dụng.
50 triệu+ địa chỉ IP dân cư trên 200+ quốc gia và khu vực — theo trang sản phẩm Residential Lite, điều này có nghĩa là việc quay sau cổng lấy từ một nhóm lớn hơn nhiều so với hầu hết các danh sách tự quản lý.
Hỗ trợ HTTP, HTTPS và SOCKS5 — các giao thức giống như ví dụ requests trong bài viết này đã sử dụng, vì vậy không có thay đổi nào trong mã yêu cầu.
Thanh toán gói trả trước — giá cả đã công bố của Nstproxy được bán theo gói tính phí thay vì theo hình thức đăng ký, điều này quan trọng nếu kịch bản xoay vòng của bạn chỉ chạy thỉnh thoảng thay vì liên tục.
Nếu bạn đang thay đổi proxy cụ thể để điều khiển một trình duyệt không giao diện thay vì chỉ các cuộc gọi requests bình thường, cấu hình proxy trong Playwright đề cập đến phiên bản ngữ cảnh trình duyệt của cùng một vấn đề.
Xoay vòng proxy trong Python là một vòng lặp thay đổi một từ điển giữa các yêu cầu, không phải là một tính năng bạn cài đặt — mọi thứ trong bài viết này, từ phiên bản ba dòng itertools.cycle đến pool thay thế an toàn với luồng, đều được xây dựng trên từ điển {"http": ..., "https": ...} mà requests luôn chấp nhận. Bắt đầu với vòng lặp cơ bản để xác nhận mã yêu cầu của bạn hoạt động, thêm vòng lặp thay thế khi bạn đang chỉ vào các proxy có thể thất bại thực sự, và chỉ sử dụng luồng khi độ trễ của yêu cầu đơn thực sự là nút thắt cổ chai của bạn.
H: Tôi có cần một thư viện đặc biệt để xoay vòng proxy trong Python, hay requests đã xử lý điều đó?
Bạn không cần một thư viện đặc biệt — requests chỉ chấp nhận một từ điển proxy cho mỗi cuộc gọi, và việc xoay vòng là vòng lặp trong mã của bạn thay đổi từ điển nào được truyền trong mỗi yêu cầu, như đã thấy trong suốt bài viết này.
H: Tại sao mã xoay vòng của tôi dường như luôn sử dụng cùng một proxy?
Kiểm tra biến môi trường HTTP_PROXY hoặc HTTPS_PROXY trước, vì tài liệu của requests xác nhận rằng nó sẽ âm thầm ghi đè bất cứ điều gì bạn đặt trên session.proxies, điều này mà bài viết này tái tạo lại.
H: Lớp Retry của urllib3 có xoay vòng các proxy cho tôi không?
Không — Retry thử lại cùng một yêu cầu trên cùng một kết nối với một độ trễ lùi, và không chuyển sang một proxy khác; bạn cần một vòng lặp xoay vòng như ví dụ thay thế trong bài viết này đi cùng với nó, chứ không phải là thay thế.
H: Có an toàn không khi xoay vòng các proxy từ nhiều luồng cùng lúc?
Nó an toàn miễn là bất kỳ thứ gì chọn "proxy tiếp theo" được bảo vệ bởi một khóa, như trong ví dụ itertools.cycle được bảo vệ bởi threading.Lock ở trên; một bộ lặp chia sẻ không được bảo vệ được truy cập từ nhiều luồng là nguồn gốc thông thường của các lỗi xoay vòng tinh vi dưới điều kiện đồng thời.
H: Sự khác biệt giữa việc xoay vòng danh sách proxy của riêng tôi và việc sử dụng một cổng xoay vòng từ nhà cung cấp là gì?
Xoay vòng danh sách của riêng bạn có nghĩa là mã của bạn theo dõi proxy nào đang hoạt động và chọn giữa chúng, trong khi một cổng xoay vòng thực hiện công việc đó dưới một máy chủ và cổng cố định ở phía nhà cung cấp, đó là mẫu mà Nstproxy tài liệu cho các Proxy Residential Lite của nó.
Hướng dẫn thực hành này so sánh ba mô hình sở hữu danh sách bằng cách sử dụng một hợp đồng ghi âm. Nó bổ sung các điều khiển khởi động lại, loại bỏ trùng lặp, mã hóa, phân trang và xác thực mà các hướng dẫn cơ bản thường bỏ qua.
Marcus Chen
Aug. 11th 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.