Không cần KYC — không cần ID, không selfie, không giấy tờ. Thanh toán bằng crypto: BTC, USDT, USDC, ETH, SOL, LTC
Ngôn ngữ: Tiếng Việt
Bắt đầu ngay

Tài liệu · Python 3.9+ · requests · httpx · aiohttp

Proxy dân cư xoay vòng trong Python: requests, httpx và aiohttp

Các mẫu production, không phải dòng lệnh đơn: retry tôn trọng Retry-After, IP mới cho mỗi request hoặc một IP cho mỗi flow, concurrency theo host trong asyncio, và byte thực sự tiêu tốn mỗi trang.

Cập nhật lần cuối: · 7 phút đọc

Trả lời nhanh

Làm sao để dùng proxy dân cư xoay vòng trong Python?

Truyền http://USERNAME:[email protected]:7777 làm proxy cho cả http và https trong requests, làm proxy= trong httpx 0.26+, hoặc proxy= cho mỗi request trong aiohttp. CrawlRelay proxy dân cư xoay vòng trên mỗi kết nối mới và giữ sticky với -session-<id> trong username. Giá là 1,50 US$ cho 1 GB và 0,50 US$/GB từ 50 GB. Thanh toán bằng crypto, không cần KYC.

Cài đặt Python xem qua

requestsproxies={"http": url, "https": url}; retry qua urllib3 Retry
httpxhttpx.Client(proxy=url); tham số proxies= cũ đã bị loại bỏ trong httpx 0.28
aiohttpsession.get(url, proxy="http://USER:PASS@host:port"), thông tin xác thực trong URL proxy
SOCKS5pip install "requests[socks]" hoặc httpx[socks], rồi socks5h:// trên cổng 7778
IP mới mỗi yêu cầuTắt keep-alive: Connection: close, max_keepalive_connections=0 hoặc force_close=True
Cùng IP cho một flow-session-<id>-ttl-<minutes> trong username, tối đa 30 phút
Scheme URL proxyLuôn dùng http:// cho cổng HTTP, ngay cả với trang web HTTPS

Làm sao để dùng proxy với requests cùng retry tôn trọng Retry-After?

Gắn một HTTPAdapter với urllib3 Retry trên một Session. Nó retry lỗi kết nối và các trạng thái bạn liệt kê, đợi theo hàm mũ, và tuân thủ header Retry-After mà site gửi cùng 429 và 503. Đặt trust_env = False để biến HTTPS_PROXY thừa không ghi đè proxy của bạn.

requests + urllib3 Retry
import os

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

USER = os.environ.get("CRAWLRELAY_USER", "USERNAME-country-us")
PASSWORD = os.environ.get("CRAWLRELAY_PASSWORD", "PASSWORD")
PROXY = "http://%s:%[email protected]:7777" % (USER, PASSWORD)

retry = Retry(
    total=4,
    connect=2,
    backoff_factor=1.0,  # waits of 0 s, 2 s, 4 s, 8 s (Retry-After wins on 429/503)
    status_forcelist=(429, 502, 503, 504),
    allowed_methods=frozenset({"GET", "HEAD"}),
    respect_retry_after_header=True,
)

session = requests.Session()
session.trust_env = False  # ignore HTTP(S)_PROXY from the environment
session.mount("http://", HTTPAdapter(max_retries=retry))
session.mount("https://", HTTPAdapter(max_retries=retry))
session.proxies = {"http": PROXY, "https": PROXY}
session.headers["User-Agent"] = "ExampleCrawler/1.0 (+https://example.com/crawler-info)"
session.headers["Connection"] = "close"  # new connection per request, so usually a new exit IP

r = session.get("https://api.ipify.org", timeout=(10, 30))
print(r.status_code, r.text)

Làm sao để tạo URL proxy an toàn nhắm mục tiêu?

Tạo username trong một hàm và kiểm tra. Lỗi gõ mã quốc gia hoặc ký tự không mã hóa trong mật khẩu dẫn tới lỗi 407 trông như lỗi xác thực. Trợ giúp dưới đây giữ đúng thứ tự tài liệu (USERNAME-country-{cc}-state-{state}-city-{city}-zip-{zip}-asn-{asn}-session-{id}-ttl-{minutes}), từ chối key lạ và mã hóa URL cả hai thông tin xác thực.

Trình tạo username và URL proxy
import re
from urllib.parse import quote

ORDER = ("country", "state", "city", "zip", "asn", "session", "ttl")
VALUE = re.compile(r"^[a-z0-9_]+$")


def build_username(base, **params):
    """build_username("USERNAME", country="us", city="new_york", session="job1", ttl=30)"""
    parts = [base]
    for key in ORDER:
        value = params.pop(key, None)
        if value is None:
            continue
        value = str(value).lower()
        if not VALUE.match(value):
            raise ValueError("bad value for %s: %r" % (key, value))
        if key == "ttl" and not 1 <= int(value) <= 30:
            raise ValueError("ttl must be 1 to 30 minutes")
        parts.append("%s-%s" % (key, value))
    if params:
        raise ValueError("unknown parameters: %s" % ", ".join(sorted(params)))
    return "-".join(parts)


def proxy_url(username, password, socks=False):
    scheme, port = ("socks5h", 7778) if socks else ("http", 7777)
    return "%s://%s:%[email protected]:%d" % (
        scheme, quote(username, safe=""), quote(password, safe=""), port)


print(proxy_url(build_username("USERNAME", country="us", state="ny", city="new_york", session="job1", ttl=20), "p@ss:word"))

Làm sao để có IP mới mỗi request với httpx?

Tắt keep-alive. httpx mặc định gom nhóm kết nối, và kết nối tái sử dụng giữ IP thoát cũ. Với max_keepalive_connections=0, mỗi request mở kết nối mới tới gateway và thường thoát ra IP dân cư khác. num_bytes_downloaded trả byte nhận được trên đường truyền, gần giống với cách tính cước traffic.

httpx: client xoay vòng
import httpx

PROXY = "http://USERNAME-country-gb:[email protected]:7777"

# No keep-alive: every request opens a new connection, so it usually gets a new exit IP
with httpx.Client(
    proxy=PROXY,
    timeout=httpx.Timeout(30.0, connect=10.0),
    limits=httpx.Limits(max_keepalive_connections=0),
    follow_redirects=True,
) as client:
    for _ in range(3):
        r = client.get("https://api.ipify.org")
        print(r.text, r.num_bytes_downloaded, "bytes on the wire")

Làm sao để crawl đồng thời với asyncio mà không tấn công cùng một site?

Giới hạn concurrency theo host, không chỉ tổng thể. Giới hạn tổng 50 cho phép 50 request cùng một site nếu danh sách URL sắp theo domain. Semaphore theo hostname giữ mỗi site ở mức lịch sự trong khi toàn bộ crawl vẫn nhanh. Bắt đầu 2 đến 4 mỗi host và xem hướng dẫn concurrency trước khi tăng.

httpx.AsyncClient với semaphore theo host
import asyncio
from collections import defaultdict
from urllib.parse import urlsplit

import httpx

PROXY = "http://USERNAME-country-us:[email protected]:7777"
PER_HOST = 4  # parallel requests per target host
host_slots = defaultdict(lambda: asyncio.Semaphore(PER_HOST))


async def fetch(client, url):
    async with host_slots[urlsplit(url).hostname]:
        try:
            r = await client.get(url)
            return url, r.status_code, r.num_bytes_downloaded
        except httpx.HTTPError as exc:
            return url, type(exc).__name__, 0


async def main(urls):
    limits = httpx.Limits(max_connections=50, max_keepalive_connections=0)
    timeout = httpx.Timeout(30.0, connect=10.0)
    async with httpx.AsyncClient(proxy=PROXY, limits=limits, timeout=timeout) as client:
        for result in await asyncio.gather(*(fetch(client, u) for u in urls)):
            print(*result)


asyncio.run(main(["https://example.com/", "https://example.org/", "https://example.net/"]))

Làm sao để dùng proxy với aiohttp?

Truyền gateway làm proxy= trên mỗi request, với thông tin xác thực trong URL proxy. Cách này hoạt động với mọi bản aiohttp 3.x mà không cảnh báo; BasicAuth và tham số proxy_auth= đã deprecated từ aiohttp 3.14 và sẽ bị bỏ ở 4.0. Một TCPConnector(force_close=True) đóng mọi kết nối sau phản hồi, mỗi request thường có IP mới. Nếu không, aiohttp tái sử dụng kết nối và bạn giữ cùng IP một thời gian.

aiohttp với thông tin xác thực trong URL proxy
import asyncio

import aiohttp

# Credentials go in the proxy URL; percent-encode a password that contains @ or :
PROXY = "http://USERNAME-country-fr:[email protected]:7777"


async def main():
    # force_close=True: one connection per request, so each request usually gets a new exit IP
    connector = aiohttp.TCPConnector(limit=20, force_close=True)
    timeout = aiohttp.ClientTimeout(total=60, sock_connect=10)
    async with aiohttp.ClientSession(connector=connector, timeout=timeout) as session:
        for _ in range(3):
            async with session.get("https://api.ipify.org", proxy=PROXY) as resp:
                print(resp.status, await resp.text())


asyncio.run(main())

Làm sao giữ một IP cho flow nhiều bước?

Tạo một session ID cho mỗi flow rồi đặt trong username với TTL dài hơn flow. Keep-alive tốt ở đây: bạn muốn cùng IP thoát. Nếu thiết bị dân cư sau session offline, IP có thể đổi trước TTL hết, nên làm flow có thể khởi động lại từ checkpoint cuối.

Sticky session với requests
import uuid

import requests

session_id = uuid.uuid4().hex[:10]  # one ID per flow, lowercase letters and digits
user = "USERNAME-country-us-state-ca-session-%s-ttl-20" % session_id
proxy = "http://%s:[email protected]:7777" % user

with requests.Session() as s:
    s.proxies = {"http": proxy, "https": proxy}
    first = s.get("https://api.ipify.org", timeout=(10, 30)).text
    second = s.get("https://api.ipify.org", timeout=(10, 30)).text
    print(first, second, "same exit" if first == second else "exit changed")

Một trình scraper Python dùng bao nhiêu traffic mỗi trang?

Đo trên 100 trang thật trước khi mua dung lượng. Ghi lại num_bytes_downloaded trong httpx, hoặc độ dài body nén trong middleware bạn tự làm, rồi nhân với số trang. Yêu cầu HTML thường tốn vài chục KB mỗi trang; hướng dẫn băng thông cho số liệu và chi phí cho 1.000 trang với giá CrawlRelay.

Ba thói quen giảm traffic mà không thay kết quả:

  • Gửi Accept-Encoding: gzip, br (httpx và requests mặc định gửi gzip) để trang nén khi truyền.
  • Lấy endpoint JSON mà trang tải khi site cho phép hoặc có tài liệu, thay vì HTML đầy đủ.
  • Bỏ qua trang không đổi với If-None-Match hoặc If-Modified-Since: một 304 Not Modified chỉ tốn vài trăm byte.

Python và proxy dân cư: các câu hỏi

requests, httpx hay aiohttp: tôi nên dùng cái nào để thu thập dữ liệu?

Dùng requests cho các script đơn giản và crawl nhỏ. Dùng httpx khi bạn muốn cùng một API cho code đồng bộ và bất đồng bộ, và hỗ trợ HTTP/2 qua httpx[http2]. Dùng aiohttp cho độ đồng thời rất cao trong asyncio thuần túy. Với crawl có lập lịch, loại trùng và pipeline, dùng Scrapy thay vì tự viết các phần đó.

Tại sao tôi lại nhận lỗi SSL: WRONG_VERSION_NUMBER khi dùng proxy trong Python?

Có thể bạn đã viết https:// trước địa chỉ proxy. Cổng 7777 của gateway dùng HTTP thuần và mở tunnel CONNECT cho các site HTTPS, nên URL proxy phải bắt đầu bằng http:// trong cả khóa http và https. Xem trang lỗi.

Làm sao để dùng proxy SOCKS5 trong Python?

Cài thêm gói (pip install "requests[socks]" hoặc pip install "httpx[socks]"), rồi dùng socks5h://USERNAME:[email protected]:7778. h gửi hostname đến proxy, DNS phân giải ở cửa ra nên bạn sẽ nhận được kết quả vùng miền giống như người dùng địa phương.

Tại sao proxy di động 4G quay vòng của tôi trả lại IP trùng lặp?

Client của bạn đã tái sử dụng kết nối giữ sống, trong khi quay vòng xảy ra trên mỗi kết nối mới. Gửi Connection: close trong requests, đặt max_keepalive_connections=0 trong httpx hoặc dùng force_close=True trong aiohttp. Cũng kiểm tra xem username có phần session- không, phần này cố định một IP.

Làm thế nào để thiết lập timeout cho các yêu cầu qua proxy?

Thiết lập rõ ràng vì requests không có timeout mặc định. Timeout kết nối khoảng 10 giây và timeout đọc 30 giây phù hợp cho trang HTML; các exit di động và mục tiêu chậm cần từ 45 đến 60 giây. Thử lại 1 lần khi timeout trên kết nối mới thay vì chờ lâu hơn. Xem cách timeout đọc.

Tôi có thể dùng các proxy này trong Jupyter hoặc với pandas không?

Có thể. Bất cứ thứ gì dùng requests hoặc httpx bên dưới đều dùng được proxy dân cư. Với pandas.read_html hoặc read_csv trên URL, tải nội dung bằng requests qua proxy trước, rồi truyền text hoặc bytes sang pandas.

Chạy scraper Python của bạn qua IP dân cư

1,50 US$ cho 1 GB, 0,50 US$/GB từ 50 GB.

Từ 0,50 US$/GB · không cần KYC

Bắt đầu ngay