Trả lời nhanh
Làm sao sử dụng proxy xoay vòng trong Node.js?
Với fetch, tạo undici ProxyAgent cho http://gw.crawlrelay.com:7777 và truyền làm dispatcher. Với axios hoặc got, truyền proxy agent như https-proxy-agent hoặc hpagent, và cấu hình proxy: false trong axios. CrawlRelay proxy dân cư đọc quốc gia và phiên từ username, từ 0,50 US$/GB. Thanh toán bằng crypto, không cần KYC.
Tổng quan cài đặt Node.js
| fetch / undici | new ProxyAgent({ uri, token }), rồi fetch(url, { dispatcher }) |
|---|---|
| axios | httpsAgent: new HttpsProxyAgent(url) và proxy: false |
| được | agent: { https: new HttpsProxyAgent({ proxy }) } từ hpagent |
| SOCKS5 | socks-proxy-agent với một URL socks5h:// trên cổng 7778 |
| IP mới mỗi yêu cầu | Một agent mới hoặc một session ID mới cho mỗi yêu cầu; các kết nối trong pool giữ lại exit của chúng |
| Định dạng module | Ví dụ là các module ES (.mjs hoặc "type": "module") với await cấp cao nhất |
Làm thế nào để tôi sử dụng proxy dân cư với fetch của Node?
fetch toàn cục của Node (fetch) được xây dựng trên undici nhưng mặc định không đọc HTTP_PROXY hoặc HTTPS_PROXY. Cài đặt undici và truyền một ProxyAgent làm dispatcher. Trường token gửi thông tin xác thực dưới dạng header Proxy-Authorization, vì vậy mật khẩu không bao giờ xuất hiện trong URL có thể bị ghi lại.
import { ProxyAgent, fetch } from "undici";
const credentials = Buffer.from("USERNAME-country-us:PASSWORD").toString("base64");
const dispatcher = new ProxyAgent({
uri: "http://gw.crawlrelay.com:7777",
token: `Basic ${credentials}`,
});
const res = await fetch("https://api.ipify.org?format=json", {
dispatcher,
signal: AbortSignal.timeout(30000),
});
console.log(res.status, await res.json());
await dispatcher.close();Làm thế nào để tôi sử dụng proxy dân cư với axios?
Không dựa vào tùy chọn proxy của axios cho các trang HTTPS: nó gửi yêu cầu đến proxy mà không có đường hầm CONNECT, điều này nhiều proxy sẽ từ chối. Tắt nó bằng proxy: false và truyền một agent mở đường hầm đúng cách.
import axios from "axios";
import { HttpsProxyAgent } from "https-proxy-agent";
const agent = new HttpsProxyAgent("http://USERNAME-country-de:[email protected]:7777");
const client = axios.create({ httpsAgent: agent, httpAgent: agent, proxy: false, timeout: 30000 });
const { data } = await client.get("https://api.ipify.org?format=json");
console.log(data.ip);Làm thế nào để tôi sử dụng proxy dân cư với got?
got dùng một agent cho mỗi giao thức. hpagent theo http.Agent của Node: giữ kết nối luôn bật bị tắt trừ khi bạn truyền keepAlive: true. Tắt nó, hoặc đặt keepAlive: false như dưới đây, khi bạn muốn mỗi yêu cầu sử dụng kết nối mới, và thường là một exit mới.
import got from "got";
import { HttpsProxyAgent } from "hpagent";
const proxy = "http://USERNAME-country-fr:[email protected]:7777";
const body = await got("https://api.ipify.org", {
agent: { https: new HttpsProxyAgent({ proxy, keepAlive: false }) },
timeout: { request: 30000 },
retry: { limit: 2, statusCodes: [429, 502, 503, 504] },
}).text();
console.log(body);Làm thế nào để tôi sử dụng SOCKS5 trong Node.js?
Dùng socks-proxy-agent với scheme socks5h:// để hostname được giải quyết tại exit. Nó hoạt động với các module http và https của Node và với bất kỳ thư viện nào chấp nhận agent.
import https from "node:https";
import { SocksProxyAgent } from "socks-proxy-agent";
const agent = new SocksProxyAgent("socks5h://USERNAME-country-gb:[email protected]:7778");
const req = https.get("https://api.ipify.org", { agent, timeout: 30000 }, (res) => {
let body = "";
res.on("data", (chunk) => (body += chunk));
res.on("end", () => console.log(res.statusCode, body));
});
req.on("timeout", () => req.destroy(new Error("timeout after 30 s")));
req.on("error", (err) => console.error(err.code, err.message));Làm thế nào tôi hạn chế đồng thời trên mỗi host mà không cần thư viện?
Promise.all trên 10.000 URL mở 10.000 yêu cầu cùng một lúc. Một bộ giới hạn nhỏ trên mỗi hostname giữ mỗi site ở mức lịch sự trong khi crawl chung chạy song song. Phiên bản dưới đây không cần phụ thuộc và hoạt động với bất kỳ client nào ở trên.
import { ProxyAgent, fetch } from "undici";
const PER_HOST = 4;
const active = new Map();
const waiting = new Map();
const dispatcher = new ProxyAgent("http://USERNAME-country-us:[email protected]:7777");
async function withHostSlot(url, task) {
const host = new URL(url).hostname;
while ((active.get(host) ?? 0) >= PER_HOST) {
await new Promise((resolve) => {
if (!waiting.has(host)) waiting.set(host, []);
waiting.get(host).push(resolve);
});
}
active.set(host, (active.get(host) ?? 0) + 1);
try {
return await task();
} finally {
active.set(host, active.get(host) - 1);
waiting.get(host)?.shift()?.();
}
}
const urls = ["https://example.com/", "https://example.org/", "https://example.net/"];
const results = await Promise.all(
urls.map((url) =>
withHostSlot(url, async () => {
const res = await fetch(url, { dispatcher, signal: AbortSignal.timeout(30000) });
return [url, res.status, (await res.arrayBuffer()).byteLength];
}).catch((err) => [url, err.name, 0])
)
);
console.table(results);
await dispatcher.close();Tại sao tôi nhận cùng một IP hai lần, hoặc ECONNRESET?
Agents gom nhóm kết nối, và một kết nối trong pool giữ exit khi mở. Để có IP mới mỗi yêu cầu, tạo một agent mới cho mỗi yêu cầu rồi đóng nó sau đó, tắt keep-alive trong agent, hoặc đặt một -session-<id> duy nhất trong username của mỗi yêu cầu.
ECONNRESET và socket hang up thường do tái sử dụng socket trong pool mà phía bên kia đã đóng, hoặc do exit bị rớt. Thử lại yêu cầu GET một lần với kết nối mới. Trang connection reset giải thích chi tiết.
Node.js và proxy: câu hỏi
Node.js fetch có hỗ trợ HTTP_PROXY không?
Không mặc định trong các phiên bản hầu hết dự án đang chạy hiện nay: fetch toàn cục bỏ qua biến môi trường proxy trừ khi bạn truyền dispatcher. Dùng một undici ProxyAgent như đã mô tả, hoặc đặt dispatcher toàn cục với setGlobalDispatcher() của undici nếu mọi yêu cầu trong tiến trình cần sử dụng proxy.
Tại sao axios lỗi ở các site HTTPS khi dùng proxy?
Tùy chọn proxy tích hợp của axios gửi HTTPS đến proxy theo cách nhiều proxy từ chối, thay vì mở đường hầm CONNECT. Đặt proxy: false và truyền một HttpsProxyAgent làm httpsAgent. Yêu cầu sau đó đi qua đường hầm chính xác, và TLS giữ giữa mã của bạn và site.
Làm sao để tôi gửi các quốc gia khác nhau từ một tiến trình Node.js?
Tạo một agent cho mỗi quốc gia, mỗi agent có username riêng như USERNAME-country-de hoặc USERNAME-country-jp, và chọn agent cho từng yêu cầu. Agents rẻ và giữ agent riêng cũng giữ pool kết nối riêng, vì vậy exit của chúng cũng riêng biệt.
Nên đặt timeout nào trong Node.js?
Luôn đặt timeout: AbortSignal.timeout(30000) cho fetch, timeout: 30000 cho axios, timeout: { request: 30000 } cho got. Ba mươi giây phù hợp cho trang HTML; cho mục tiêu chậm và exit di động 4G đến 60 giây, và thử lại một lần với kết nối mới thay vì đợi lâu hơn.
Kết nối trình thu thập dữ liệu Node.js của bạn
5,94 US$ cho 10 GB, 0,50 US$/GB từ 50 GB.