[{"data":1,"prerenderedAt":20},["ShallowReactive",2],{"blog:post:vi:cach-chon-proxy-cho-scraper-python":3},{"slug":4,"lang":5,"title":6,"summary":7,"date":8,"tags":9,"tag_slugs":15,"thumbnail_url":16,"translations":17,"body":18,"asset_base":19},"cach-chon-proxy-cho-scraper-python","vi","Cách chọn proxy cho scraper Python không bị chặn","Hướng dẫn chọn loại proxy, cấu hình sticky/rotating và xác thực để scraper Python chạy ổn định mà không bị chặn IP.","2026-10-20",[10,11,12,13,14],"proxy","scraper","python","http-proxy","web-scraping",[10,11,12,13,14],"https://blog-api.ro-proxy.com/api/blog/posts/cach-chon-proxy-cho-scraper-python/thumbnail.svg?lang=vi",[5],"## Tại sao việc chọn proxy đúng với scraper Python lại quan trọng\n\nKhi scraper Python gửi hàng trăm hoặc hàng ngàn yêu cầu đến cùng một máy chủ, IP gốc của bạn sẽ nhanh chóng bị đưa vào danh sách chặn (blacklist). Proxy giúp ẩn IP thật và phân phát tải đều qua nhiều IP, nhưng không phải loại proxy nào cũng phù hợp với mọi trường hợp. Lựa chọn sai proxy — ví dụ dùng residential proxy cho trang không kiểm tra địa lý, hoặc dùng datacenter proxy cho trang chặn proxy rộng rãi — sẽ khiến thời gian phát triển và duy trì scraper tăng lên đáng kể.\n\nDưới đây là quy trình cụ thể để chọn proxy phù hợp, từ xác định nhu cầu cho đến cấu hình chi tiết trong Python.\n\n## Xác định nhu cầu thực tế của scraper\n\n### Xác định mục tiêu thu thập\n\nTrước khi chọn proxy, hãy trả lời nhanh các câu hỏi sau:\n\n- **Số lượng yêu cầu**: Dưới 1000 yêu cầu/ngày có thể dùng IP gốc, nhưng từ 5000 trở lên cần proxy.\n- **Tần suất**: Gửi 1 yêu cầu/giây thấp nguy cơ chặn, còn 10 yêu cầu/giây cần proxy rotating để luân phiên IP.\n- **Trang mục tiêu**: Trang có kiểm tra địa lý (geo-fencing) thì cần residential proxy ở quốc gia đúng.\n- **Thời gian chạy**: Scraper chạy liên tục 24/7 cần cấu hình sticky session để tránh thay đổi IP giữa các request trong một phiên.\n\n### Ví dụ thực tế\n\nMột công ty thu thập giá sản phẩm từ Shopee và Tiki mỗi 10 phút một lần với 200 URL. Vì hai trang này thường xuyên cập nhật mã CAPTCHA và kiểm tra địa lý Việt Nam, nên cần:\n\n- **Loại proxy**: Residential proxy tại Việt Nam.\n- **Chế độ xoay**: Sticky session trong vòng 5 phút để duy trì phiên đăng nhập.\n- **Tốc độ**: Ít nhất 20 IP để tránh rate limit.\n\n## Hiểu rõ các loại proxy và đặc điểm\n\n| Loại proxy | Đặc điểm | Phù hợp với | Rủi ro |\n|----------|----------|-------------|--------|\n| **Datacenter** | Tốc độ cao, giá rẻ, dễ bị chặn | Trang không kiểm tra địa lý | Dễ bị block |\n| **Residential** | IP thật từ người dùng, khó bị chặn | Trang có kiểm tra địa lý | Giá cao |\n| **Mobile** | IP từ SIM thật, khó nhận biết | Trang chặn proxy tổng thể | Rất đắt |\n| **ISP** | Kết hợp giữa datacenter và residential | Cân bằng tốc độ và độ tin cậy | Hạn chế nhà cung cấp |\n\n### Khi nào dùng Datacenter\n\nDatacenter proxy phù hợp cho các trường hợp sau:\n\n- Thu thập dữ liệu từ API công cộng không có cơ chế chặn.\n- Kiểm tra tốc độ tải trang.\n- Phát triển và test ban đầu.\n\nLưu ý: Trước khi mua gói datacenter, hãy kiểm tra trước 1 IP bằng cách gửi request đến trang mục tiêu để chắc chắn chưa bị chặn.\n\n### Khi nào chuyển sang Residential\n\nNếu scraper nhận được lỗi 403, 429 hoặc CAPTCHA liên tục, đã đến lúc chuyển sang residential proxy. Tuy nhiên, residential proxy có giá cao hơn nên nên dùng kết hợp với rotating proxy để tối ưu chi phí.\n\n## Cấu hình HTTP(S) proxy trong Python requests\n\n### Cách cơ bản\n\n```python\nimport requests\n\nproxies = {\n    \"http\": \"http://user:pass@proxy_ip:port\",\n    \"https\": \"https://user:pass@proxy_ip:port\",\n}\n\nresponse = requests.get(\"https://example.com\", proxies=proxies)\nprint(response.status_code)\n```\n\n### Cấu hình authentication\n\nNhiều dịch vụ proxy yêu cầu xác thực qua username và password. Cách truyền trực tiếp trong URL có thể gây lỗi với một số proxy, nên nên dùng cách sau:\n\n```python\nfrom requests.auth import HTTPProxyAuth\n\nproxies = {\n    \"http\": \"http://proxy_ip:port\",\n    \"https\": \"https://proxy_ip:port\",\n}\n\nauth = HTTPProxyAuth(\"username\", \"password\")\nresponse = requests.get(\"https://example.com\", proxies=proxies, auth=auth)\n```\n\n### Sử dụng session để tận dụng sticky proxy\n\nĐể duy trì cùng một IP trong một phiên làm việc (sticky session), hãy sử dụng `requests.Session()`:\n\n```python\nimport requests\n\nsession = requests.Session()\nsession.proxies.update({\n    \"http\": \"http://user:pass@proxy_ip:port\",\n    \"https\": \"https://user:pass@proxy_ip:port\",\n})\n\n# Các request sau sẽ dùng cùng một proxy\nfor url in urls:\n    response = session.get(url)\n```\n\n## Rotating proxy: cách xoay IP tự động\n\n### Tại sao cần rotating\n\nRotating proxy giúp phân phát tải đều qua nhiều IP và tránh bị rate limit. Tuy nhiên, một số trang yêu cầu duy trì cùng IP trong thời gian ngắn để xác thực phiên.\n\n### Cách cấu hình với thư viện requests-rotating\n\n```bash\npip install requests-rotating\n```\n\n```python\nfrom requests_rotating import RotatingProxies\n\nproxies_pool = [\n    \"http://user:pass@ip1:port\",\n    \"http://user:pass@ip2:port\",\n    \"http://user:pass@ip3:port\",\n]\n\nrotator = RotatingProxies(proxies_pool)\n\nfor url in urls:\n    proxy = rotator.get_proxy()\n    response = requests.get(url, proxies={\"https\": proxy})\n```\n\n### Rotating thủ công với round-robin\n\nNếu không muốn dùng thư viện bổ sung, có thể cài đặt đơn giản bằng iterator:\n\n```python\nfrom itertools import cycle\n\nproxy_pool = cycle([\n    \"http://user:pass@ip1:port\",\n    \"http://user:pass@ip2:port\",\n])\n\nfor url in urls:\n    proxy = next(proxy_pool)\n    response = requests.get(url, proxies={\"https\": proxy})\n```\n\n## Kiểm tra proxy trước khi dùng\n\n### Bước 1: Kiểm tra kết nối\n\n```python\nimport requests\n\ndef check_proxy(proxy_url):\n    try:\n        response = requests.get(\n            \"https://httpbin.org/ip\",\n            proxies={\"https\": proxy_url},\n            timeout=10\n        )\n        return response.status_code == 200\n    except Exception:\n        return False\n\nproxy_list = [\"http://ip1:port\", \"http://ip2:port\"]\nvalid_proxies = [p for p in proxy_list if check_proxy(p)]\n```\n\n### Bước 2: Kiểm tra địa lý\n\n```python\nimport requests\n\ndef get_geo(proxy_url):\n    response = requests.get(\n        \"https://ipinfo.io/json\",\n        proxies={\"https\": proxy_url},\n        timeout=10\n    )\n    return response.json().get(\"country\")\n\n# Chỉ giữ lại proxy ở Việt Nam (VN)\nvn_proxies = [p for p in valid_proxies if get_geo(p) == \"VN\"]\n```\n\n### Bước 3: Theo dõi tốc độ\n\n```python\nimport time\nimport requests\n\ndef measure_latency(proxy_url):\n    start = time.time()\n    response = requests.get(\n        \"https://httpbin.org/delay/1\",\n        proxies={\"https\": proxy_url},\n        timeout=5\n    )\n    return time.time() - start\n\nfast_proxies = sorted(valid_proxies, key=measure_latency)[:10]\n```\n\n## Xử lý lỗi phổ biến\n\n### Lỗi kết nối (Connection Error)\n\nThường xảy ra khi proxy không phản hồi. Cách xử lý:\n\n- Thử lại với proxy khác.\n- Kiểm tra timeout và tăng thời gian chờ.\n- Log lỗi để loại bỏ proxy không ổn.\n\n### Lỗi xác thực (407 Proxy Authentication Required)\n\nĐảm bảo định dạng URL proxy đúng: `protocol://username:password@ip:port`. Một số proxy yêu cầu encoding URL.\n\n### Lỗi 429 Too Many Requests\n\nNếu proxy rotating vẫn nhận được 429, có hai nguyên nhân:\n\n1. IP đang bị chặn từ trước — cần bỏ khỏi pool.\n2. Tần suất gửi yêu cầu quá nhanh — thêm `time.sleep()` giữa các request.\n\n## Tối ưu chi phí và hiệu năng\n\n### Kết hợp sticky + rotating\n\nDùng sticky proxy cho các request cần xác thực (login, checkout), và rotating proxy cho các request độc lập (lấy sản phẩm, lấy giá).\n\n### Pool management\n\nDuy trì một pool proxy lớn hơn nhu cầu thực tế để dự phòng:\n\n- Nếu cần 20 IP nhưng chỉ có 10, tăng dần lên 25 để tránh thiếu hụt.\n- Định kỳ kiểm tra và loại bỏ proxy không hoạt động.\n\n### Retry logic\n\n```python\nimport time\nimport requests\n\ndef fetch_with_retry(url, proxy, retries=3):\n    for attempt in range(retries):\n        try:\n            response = requests.get(url, proxies={\"https\": proxy}, timeout=10)\n            if response.status_code == 200:\n                return response\n        except Exception:\n            pass\n        time.sleep(2 ** attempt)  # Exponential backoff\n    return None\n```\n\n## Kết luận\n\nViệc chọn proxy phù hợp cho scraper Python không chỉ là vấn đề kỹ thuật mà còn là chiến lược. Hãy bắt đầu với nhu cầu thực tế, kiểm tra kỹ lưỡng trước khi triễn khai, và luôn chuẩn bị fallback proxy để đảm bảo scraper chạy ổn định trong dài hạn.\n","https://blog-api.ro-proxy.com/api/blog/posts/cach-chon-proxy-cho-scraper-python/assets",1792821467365]