Dùng proxy với Scrapy — cấu hình có mật khẩu, giới hạn tốc độ, xử lý lỗi và đổi IP giữa các lần chạy
Trong bài này
Scrapy là framework thu thập dữ liệu phổ biến nhất của Python, và nó hỗ trợ proxy sẵn — chỉ là tài liệu nằm rải rác. Bài này gom lại những gì bạn cần: hai cách gắn proxy có tài khoản, mật khẩu, bộ cấu hình tốc độ "lịch sự" để không bị chặn, cách kiểm tra proxy đang chạy, các lỗi hay gặp, và cách đổi IP với proxy 4G mà không làm hỏng lần chạy.
Scrapy dùng proxy như thế nào
Scrapy có sẵn HttpProxyMiddleware, bật mặc định. Nó lấy proxy từ hai nơi:
- biến môi trường
http_proxyvàhttps_proxy, đọc một lần khi Scrapy khởi động, request.meta["proxy"]của từng request — ưu tiên hơn biến môi trường.
Tài khoản, mật khẩu viết thẳng trong địa chỉ proxy (http://USER:PASS@HOST:PORT) — Scrapy tự tách ra và gửi header xác thực cho proxy.
Lưu ý: Scrapy chỉ hỗ trợ proxy HTTP/HTTPS, không hỗ trợ SOCKS5. Với 65Proxy, hãy dùng thông tin kết nối HTTP. Khác biệt giữa hai loại có trong bài SOCKS5 và HTTP proxy.
Cách 1: biến môi trường
Cách nhanh nhất, áp dụng cho mọi request. Cả hai biến đều dùng http:// ở đầu, kể cả https_proxy, vì Scrapy nói chuyện với proxy bằng HTTP:
export https_proxy="http://USER:PASS@HOST:PORT"
export http_proxy="$https_proxy"
scrapy crawl prices -O prices.jsonTrên Windows PowerShell:
$env:HTTPS_PROXY = "http://USER:PASS@HOST:PORT"
$env:HTTP_PROXY = $env:HTTPS_PROXY
scrapy crawl prices -O prices.jsonCách 2: middleware riêng trong dự án
Khi muốn kiểm soát trong code — ví dụ chỉ dùng proxy cho một số tên miền — hãy viết một middleware nhỏ đặt meta["proxy"]. Trong middlewares.py:
import os
class ProxyMiddleware:
def __init__(self):
self.proxy = os.environ["PROXY"] # http://USER:PASS@HOST:PORT
def process_request(self, request, spider=None):
request.meta.setdefault("proxy", self.proxy)Rồi bật nó trong settings.py, với số thứ tự nhỏ hơn 750 để chạy trước HttpProxyMiddleware:
DOWNLOADER_MIDDLEWARES = {
"myproject.middlewares.ProxyMiddleware": 350,
}Đổi myproject thành tên dự án của bạn. Đọc proxy từ biến môi trường giúp tài khoản, mật khẩu không nằm trong code.
Cấu hình tốc độ lịch sự
Với proxy 4G, mọi request đi ra từ một IP — nên tốc độ quan trọng hơn bao giờ hết. Bộ cấu hình khởi đầu hợp lý cho settings.py:
ROBOTSTXT_OBEY = True
USER_AGENT = "my-crawler/1.0 (+mailto:[email protected])"
CONCURRENT_REQUESTS_PER_DOMAIN = 2
DOWNLOAD_DELAY = 2 # giây; Scrapy tự dao động 0,5–1,5 lần
DOWNLOAD_TIMEOUT = 30 # mặc định 180 giây là quá lâu
AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_START_DELAY = 2
AUTOTHROTTLE_MAX_DELAY = 60
AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
RETRY_TIMES = 3
RETRY_HTTP_CODES = [500, 502, 503, 504, 522, 524, 408, 429]
HTTPCACHE_ENABLED = True # khi phát triển: không tải lại trang đã có- AutoThrottle tự giãn tốc độ khi trang phản hồi chậm.
- Middleware thử lại mặc định không chờ theo
Retry-After. Nếu bạn gặp 429 thường xuyên, hãy tăngDOWNLOAD_DELAYvà giảmCONCURRENT_REQUESTS_PER_DOMAINthay vì tăng số lần thử. Ý nghĩa từng mã lỗi có trong bài lỗi 403, 429, 503 khi scrape. - Bộ đệm HTTP khi phát triển giúp bạn sửa code bóc tách mà không tải lại trang từ trang đích — tắt nó khi chạy thật nếu cần dữ liệu mới.
Kiểm tra proxy đang chạy
Lệnh scrapy fetch tải một trang với cấu hình hiện tại và in nội dung ra màn hình:
scrapy fetch --nolog https://api.ipify.orgKết quả phải là IP của proxy, không phải IP nhà bạn. Muốn xem thêm nhà mạng và quốc gia:
scrapy fetch --nolog https://ipinfo.io/jsonĐổi IP giữa các lần chạy
Với proxy 4G, đổi IP nghĩa là gọi link đổi IP của proxy và chờ thiết bị kết nối lại. Trong Scrapy, cách sạch nhất là đổi IP giữa các lần chạy, không phải giữa từng request:
- đổi IP giữa chừng làm cookie và phiên không còn khớp với IP,
- các request đang chạy dở sẽ lỗi trong lúc thiết bị kết nối lại,
- và mỗi proxy 65Proxy đổi IP tối đa một lần mỗi 5 phút.
Một script chạy trước mỗi lần crawl (link đổi IP để trong biến môi trường ROTATE_URL):
export https_proxy="http://USER:PASS@HOST:PORT"
export http_proxy="$https_proxy"
old=$(curl -s -m 15 -x "$https_proxy" https://api.ipify.org)
curl -s -m 60 "$ROTATE_URL" > /dev/null
for i in $(seq 1 20); do
sleep 3
new=$(curl -s -m 10 -x "$https_proxy" https://api.ipify.org)
if [ -n "$new" ] && [ "$new" != "$old" ]; then break; fi
done
echo "IP: $old -> $new"
scrapy crawl prices -O prices.jsonBản Python và Node.js của vòng chờ này có trong bài đổi IP proxy bằng API.
Lỗi thường gặp
- 407 Proxy Authentication Required — sai tài khoản, mật khẩu. Nếu mật khẩu có ký tự đặc biệt, mã hoá nó trong địa chỉ proxy:
@thành%40,:thành%3A. - TunnelError: Could not open CONNECT tunnel — proxy từ chối mở đường hầm cho HTTPS; thường do sai thông tin đăng nhập, sai cổng, hoặc dùng nhầm cổng SOCKS5.
- Lỗi khi dùng
socks5://— Scrapy không hỗ trợ SOCKS; chuyển sang cổng HTTP. - Timeout hàng loạt trong một lúc — thường là lúc proxy đang đổi IP hoặc sóng yếu;
RETRY_TIMESvàDOWNLOAD_TIMEOUThợp lý sẽ xử lý. - IP vẫn là IP nhà bạn — biến môi trường đặt sau khi Scrapy đã khởi động, hoặc đặt trong một cửa sổ terminal khác.
Các lỗi chung của proxy có trong bài các lỗi proxy thường gặp.
Proxy 4G Singapore của 65Proxy cho Scrapy
Proxy của chúng tôi có cổng HTTP với tài khoản, mật khẩu — đúng thứ Scrapy cần — và link đổi IP theo yêu cầu (tối đa một lần mỗi 5 phút). IP nhà mạng di động Singapore giúp bạn truy cập dữ liệu công khai trên những trang chặn IP máy chủ, hoặc dữ liệu chỉ hiện với khách Singapore. 200GB mỗi gói, giá 1 ngày $4, 7 ngày $13, 1 tháng $40. Hãy dùng nó cùng bộ cấu hình tốc độ ở trên và tôn trọng quy định của từng trang — xem scrape dữ liệu có hợp pháp không và bảng giá.
Câu hỏi thường gặp
Một proxy 4G có đủ cho Scrapy không?
Với thu thập dữ liệu lịch sự — vài request mỗi giây trở xuống trên mỗi trang — thường là đủ. Nếu bạn cần tốc độ cao hơn nhiều, hãy hỏi trang đích về API trước khi nghĩ tới thêm IP.
Có middleware xoay proxy cho Scrapy không?
Có những thư viện xoay qua một danh sách proxy. Với một proxy 4G đổi IP theo link, bạn không cần chúng — chỉ cần đổi IP giữa các lần chạy như ở trên.
Scrapy có chạy được JavaScript không?
Bản thân Scrapy thì không. Với trang cần JavaScript, hãy tìm API mà trang gọi, hoặc dùng trình duyệt headless — xem scrape trang JavaScript.