[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog:post:vi:cau-hinh-proxy-cho-python-aiohttp-de-scraping-bat-dong-bo-hieu-qua":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},"cau-hinh-proxy-cho-python-aiohttp-de-scraping-bat-dong-bo-hieu-qua","vi","Cấu hình proxy cho Python aiohttp để scraping bất đồng bộ hiệu quả","Hướng dẫn chi tiết cách tích hợp proxy xoay và sticky vào client aiohttp của Python, xử lý lỗi kết nối, tối ưu hiệu suất scraping bất đồng bộ với RoProxy.","2026-08-26",[10,11,12,13,14],"python","aiohttp","proxy","scraping","async",[10,11,12,13,14],"https://blog-api.ro-proxy.com/api/blog/posts/cau-hinh-proxy-cho-python-aiohttp-de-scraping-bat-dong-bo-hieu-qua/thumbnail.svg?lang=vi",[5],"## Tại sao cần proxy khi scraping với aiohttp?\n\nKhi chạy scraper bất đồng bộ với `aiohttp`, các request đi ra từ cùng một địa chỉ IP rất dễ bị trang web chặn do:\n- Giới hạn tốc độ (rate limit) theo IP.\n- Phát hiện bot qua fingerprint và hành vi request.\n- Yêu cầu truy cập nội dung theo vùng địa lý (geo‑blocking).\n\nProxy giải quyết ba vấn đề trên bằng cách thay đổi IP xuất phát, cho phép bạn:\n1. Xoay IP sau mỗi request hoặc theo phiên (sticky session).\n2. Chọn IP tại quốc gia cần thiết để kiểm tra nội dung đa ngôn ngữ.\n3. Giảm nguy cơ bị liệt kê đen (blacklist) vì lưu lượng được phân tán.\n\nRoProxy cung cấp pool proxy residential, datacenter và mobile với API xoay IP tự động, phù hợp cho các tác vụ scraping quy mô lớn.\n\n## Chuẩn bị môi trường\n\n```bash\npip install aiohttp aiohttp-socks tenacity\n```\n\n- `aiohttp`: client HTTP bất đồng bộ hiệu năng cao.\n- `aiohttp-socks`: hỗ trợ proxy SOCKS5 (RoProxy cung cấp cả HTTP và SOCKS5).\n- `tenacity`: thư viện retry linh hoạt, giúp xử lý lỗi mạng tự động.\n\n## Cấu hình proxy cơ bản\n\nĐoạn mã sau minh hoạ một GET request đơn giản qua proxy HTTP:\n\n```python\nimport aiohttp\n\nPROXY_URL = \"http://user:pass@proxy.roproxy.com:8000\"\n\nasync def fetch(session, url):\n    async with session.get(url, proxy=PROXY_URL) as resp:\n        return await resp.text()\n\nasync def main():\n    async with aiohttp.ClientSession() as session:\n        html = await fetch(session, \"https://httpbin.org/ip\")\n        print(html)\n\nif __name__ == \"__main__\":\n    import asyncio\n    asyncio.run(main())\n```\n\n**Giải thích**:\n- `PROXY_URL` chứa thông tin xác thực (username:password) và endpoint proxy.\n- Tham số `proxy=` trong `session.get` áp dụng cho request đó mà không ảnh hưởng các request khác.\n\n## Sử dụng proxy xoay (rotating) với RoProxy\n\nRoProxy cho phép xoay IP qua endpoint `/rotate` hoặc cung cấp danh sách proxy sẵn có. Cách đơn giản nhất là lấy một proxy mới trước mỗi batch request:\n\n```python\nimport aiohttp\nimport asyncio\n\nROTATE_API = \"https://api.roproxy.com/v1/rotate?token=YOUR_TOKEN\"\n\nasync def get_proxy(session):\n    async with session.get(ROTATE_API) as resp:\n        data = await resp.json()\n        return f\"http://{data['username']}:{data['password']}@{data['host']}:{data['port']}\"\n\nasync def fetch_with_rotate(session, url):\n    proxy = await get_proxy(session)\n    async with session.get(url, proxy=proxy) as resp:\n        return await resp.text()\n\nasync def main():\n    async with aiohttp.ClientSession() as session:\n        tasks = [fetch_with_rotate(session, f\"https://httpbin.org/ip?i={i}\") for i in range(10)]\n        results = await asyncio.gather(*tasks)\n        for r in results:\n            print(r)\n\nasyncio.run(main())\n```\n\nLưu ý: RoProxy cũng hỗ trợ **sticky session** bằng cách thêm tham số `session_id` vào API rotate, giúp giữ nguyên IP trong một khoảng thời gian (ví dụ 10 phút).\n\n## Triển khai sticky session khi cần thiết\n\nMột số trang web yêu cầu đăng nhập hoặc giữ giỏ hàng, do đó bạn cần cùng một IP cho nhiều request liên tiếp. Ví dụ:\n\n```python\nSTICKY_API = \"https://api.roproxy.com/v1/sticky?token=YOUR_TOKEN&session_id=mysession&ttl=600\"\n\nasync def get_sticky_proxy(session):\n    async with session.get(STICKY_API) as resp:\n        data = await resp.json()\n        return f\"http://{data['username']}:{data['password']}@{data['host']}:{data['port']}\"\n```\n\nSử dụng `get_sticky_proxy` thay cho `get_proxy` trong các hàm scraping cần duy trì phiên.\n\n## Xử lý lỗi và retry tự động\n\nMạng không ổn định hoặc proxy bị chặn có thể gây ra exception. `tenacity` giúp retry với backoff exponent:\n\n```python\nfrom tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type\nimport aiohttp.ClientError\n\n@retry(\n    wait=wait_exponential(multiplier=1, min=2, max=10),\n    stop=stop_after_attempt(3),\n    retry=retry_if_exception_type(aiohttp.ClientError)\n)\nasync def safe_fetch(session, url, proxy):\n    async with session.get(url, proxy=proxy, timeout=aiohttp.ClientTimeout(total=15)) as resp:\n        resp.raise_for_status()\n        return await resp.text()\n```\n\nKết hợp với `safe_fetch` trong các task scraping để tăng độ bền vững.\n\n## Ví dụ hoàn chỉnh: scraper bất đồng bộ thu thập dữ liệu từ nhiều trang\n\n```python\nimport asyncio\nimport aiohttp\nfrom tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type\nimport aiohttp.ClientError\n\nROTATE_API = \"https://api.roproxy.com/v1/rotate?token=YOUR_TOKEN\"\nSEM = asyncio.Semaphore(20)  # giới hạn 20 request đồng thời\n\nasync def get_proxy(session):\n    async with session.get(ROTATE_API) as resp:\n        data = await resp.json()\n        return f\"http://{data['username']}:{data['password']}@{data['host']}:{data['port']}\"\n\n@retry(\n    wait=wait_exponential(multiplier=1, min=2, max=10),\n    stop=stop_after_attempt(3),\n    retry=retry_if_exception_type(aiohttp.ClientError)\n)\nasync def fetch_page(session, url):\n    async with SEM:\n        proxy = await get_proxy(session)\n        async with session.get(url, proxy=proxy, timeout=aiohttp.ClientTimeout(total=20)) as resp:\n            resp.raise_for_status()\n            return await resp.text()\n\nasync def main(urls):\n    async with aiohttp.ClientSession() as session:\n        tasks = [fetch_page(session, u) for u in urls]\n        pages = await asyncio.gather(*tasks, return_exceptions=True)\n        for i, page in enumerate(pages):\n            if isinstance(page, Exception):\n                print(f\"[ERROR] {urls[i]} -> {page}\")\n            else:\n                print(f\"[OK] {urls[i]} length={len(page)}\")\n\nif __name__ == \"__main__\":\n    target_urls = [f\"https://example.com/page/{i}\" for i in range(1, 101)]\n    asyncio.run(main(target_urls))\n```\n\n**Điểm nổi bật**:\n- `Semaphore` kiểm soát độ song song, tránh quá tải proxy và server đích.\n- Mỗi request tự động lấy proxy mới → IP luôn thay đổi.\n- Retry với backoff giúp vượt qua lỗi transient.\n\n## Tối ưu hiệu suất: connection pooling, keep‑alive, limit concurrency\n\n1. **Reuse `ClientSession`** – Tạo một session duy nhất cho toàn bộ chương trình để tận dụng connection pool của `aiohttp`.\n2. **Đặt `limit` và `limit_per_host`** trong `aiohttp.TCPConnector`:\n   ```python\n   connector = aiohttp.TCPConnector(limit=100, limit_per_host=20, ttl_dns_cache=300)\n   async with aiohttp.ClientSession(connector=connector) as session:\n       ...\n   ```\n3. **Bật keep‑alive** (mặc định đã bật) và điều chỉnh `keepalive_timeout` nếu cần.\n4. **Giảm overhead DNS** bằng `ttl_dns_cache` và `use_dns_cache=True`.\n5. **Theo dõi latency** – Ghi log thời gian phản hồi của mỗi proxy, loại bỏ proxy chậm khỏi pool.\n\n## Kết luận & lời khuyên sử dụng RoProxy\n\n- **Chọn loại proxy phù hợp**: residential cho độ tin cậy cao, datacenter cho tốc độ, mobile khi cần IP di động thực.\n- **Kết hợp rotating + sticky**: dùng rotating cho crawl rộng, sticky cho luồng đăng nhập/đặt hàng.\n- **Giám sát sức khỏe proxy** – Tích hợp Prometheus/Grafana (xem bài “Tự động hóa kiểm tra sức khỏe proxy với Prometheus và RoProxy”) để phát hiện proxy down sớm.\n- **Tuân thủ pháp lý và robots.txt** – Luôn kiểm tra điều khoản sử dụng của trang đích trước khi scraping quy mô lớn.\n\nVới các mẫu mã trên, bạn có thể xây dựng scraper `aiohttp` mạnh mẽ, bền vững và sẵn sàng mở rộng. Hãy thử ngay với tài khoản dùng thử RoProxy để trải nghiệm pool proxy chất lượng cao, xoay IP tự động và hỗ trợ SOCKS5/HTTP đầy đủ.\n","https://blog-api.ro-proxy.com/api/blog/posts/cau-hinh-proxy-cho-python-aiohttp-de-scraping-bat-dong-bo-hieu-qua/assets"]