Node.js使用代理需要乜嘢?
Node.js內置fetch由undici庫驅動,默認唔會讀取代理設置。所以HTTP代理要用undici嘅ProxyAgent作為dispatcher傳入,SOCKS5代理就用socks-proxy-agent作為agent傳入Node嘅https模組。
示例使用 IP 198.51.100.23,HTTP 端口 8000,SOCKS5 端口 1080,用戶名 spx_user,密碼 spx_pass。所有代碼均為 ES 模塊格式 (.mjs)。
npm install undici socks-proxy-agent如何將HTTP代理連接至fetch?
ProxyAgent傳入代理地址,用戶名同密碼用Basic認證值傳入token選項。undici導入嘅fetch用dispatcher傳入,請求就會經代理。HTTPS地址會用CONNECT方式加密傳送。
重複使用相同的ProxyAgent進行多個請求,連接會被重用,速度更快。每個代理創建一個代理並輪流使用即可。
import { fetch, ProxyAgent } from "undici";
const agent = new ProxyAgent({
uri: "http://198.51.100.23:8000",
token: "Basic " + Buffer.from("spx_user:spx_pass").toString("base64"),
});
const res = await fetch("https://api.ipify.org?format=json", { dispatcher: agent });
console.log(res.status, await res.json()); // "ip" should be the proxy IP如何連接 SOCKS5 代理?
socks-proxy-agent需與Node的http/https模組搭配使用。使用socks5h地址時,域名解析將由代理伺服器處理。此範例透過https.get傳遞agent並收集響應內容輸出。
如axios等運行於http模組之上嘅庫,只需在httpAgent及httpsAgent傳遞相同agent即可透過SOCKS5發送請求。
import https from "node:https";
import { SocksProxyAgent } from "socks-proxy-agent";
const agent = new SocksProxyAgent("socks5h://spx_user:spx_pass@198.51.100.23:1080");
https.get("https://api.ipify.org?format=json", { agent }, (res) => {
let body = "";
res.on("data", (chunk) => (body += chunk));
res.on("end", () => console.log(res.statusCode, body));
}).on("error", (err) => console.error("request failed:", err.message));如何通過API獲取列表並循環使用?
開始時透過API獲取列表,為每個代理創建代理器,每次請求使用下一個代理的方式。以下代碼以ip:port:user:pass格式獲取HTTP列表,創建ProxyAgent數組,失敗時嘗試下一個代理。
請在請求中加入AbortSignal.timeout設置時間限制。如果無回應的請求積累,整個任務會變慢。
import { fetch, ProxyAgent } from "undici";
const API = "https://socks5proxy.io/api/v1";
const KEY = "YOUR_API_KEY";
const text = await (await fetch(API + "/proxies/download?format=ip:port:user:pass&protocol=http", {
headers: { Authorization: "Bearer " + KEY },
})).text();
const agents = text.trim().split("\n").map((line) => {
const [ip, port, user, pass] = line.trim().split(":");
return new ProxyAgent({
uri: "http://" + ip + ":" + port,
token: "Basic " + Buffer.from(user + ":" + pass).toString("base64"),
});
});
let i = 0;
async function get(url, tries = 3) {
for (let t = 0; t < tries; t++) {
const dispatcher = agents[i++ % agents.length];
try {
const res = await fetch(url, { dispatcher, signal: AbortSignal.timeout(20000) });
if (res.ok) return await res.text();
} catch {
// try the next proxy
}
}
return null;
}
console.log((await get("https://example.com/"))?.length);使用 IP 授權後代碼如何修改?
在儀表板中註冊運行Node.js的伺服器的IPv4地址,這樣在ProxyAgent中只需填入地址,無需使用token選項。SOCKS5也可以像socks5h://198.51.100.23:1080這樣無需用戶名和密碼使用。無需將密碼放在環境變量或代碼中,這樣更容易在多台伺服器上部署。
若使用axios應如何連接?
axios運行於Node嘅http及https模組之上,可透過傳遞agent使用代理。SOCKS5需將socks-proxy-agent設為httpAgent及httpsAgent,並將axios自身嘅proxy選項設為false以避免設定衝突。
HTTP 代理可以通過 axios 的 proxy 選項設置 host、port、auth,但在 HTTPS 地址中使用代理的方式更穩定。使用 https-proxy-agent 包可以以相同結構連接 HTTP 代理。
import axios from "axios";
import { SocksProxyAgent } from "socks-proxy-agent";
const agent = new SocksProxyAgent("socks5h://spx_user:spx_pass@198.51.100.23:1080");
const client = axios.create({ httpAgent: agent, httpsAgent: agent, proxy: false, timeout: 20000 });
const { data } = await client.get("https://api.ipify.org?format=json");
console.log(data);同時發送多個請求時需要注意什麼?
用Promise.all同時發起幾千個請求會開啟太多連接,對代理同目標網站都造成負擔。設定並發處理數量,用工作隊列控制。可以自建簡單函數,或者用p-limit等套件。
均勻分配各代理的並發連接數可避免單一IP過載。共享方案包含500並發連接,請將總並發請求控制在該範圍內。
可以使用環境變量為所有請求應用代理嗎?
undici的EnvHttpProxyAgent會讀取HTTP_PROXY、HTTPS_PROXY、NO_PROXY環境變數設定代理。透過setGlobalDispatcher註冊後,該進程所有fetch請求均經代理傳送,適用於多函式庫整合情境。
全局設置會讓所有請求使用相同的IP,因此更適合需要從一個國家訪問的工具或測試,而不是需要分開使用IP的數據收集任務。如果需要輪換,可以像前面提到的那樣,在每個請求中傳遞dispatcher。
// HTTPS_PROXY=http://spx_user:spx_pass@198.51.100.23:8000 node app.mjs
import { EnvHttpProxyAgent, setGlobalDispatcher, fetch } from "undici";
setGlobalDispatcher(new EnvHttpProxyAgent());
const res = await fetch("https://api.ipify.org");
console.log(await res.text());如何解決常見問題?
如果Node.js內置fetch傳入dispatcher好似被忽略,請檢查係咪從undici套件一齊導入fetch。內置fetch同安裝undici版本唔同可能導致代理唔匹配,最穩陣係從同一個套件導入fetch同ProxyAgent。
407回應表示認證信息錯誤。請檢查token值中Basic後是否包含經base64轉換的用戶名:密碼。ECONNREFUSED通常表示端口錯誤。HTTP代理請使用HTTP端口,SOCKS代理請使用SOCKS5端口。
- fetch與ProxyAgent同屬undici套件
- 407:檢查token值及註冊IP
- ECONNREFUSED: HTTP 端口和 SOCKS5 端口的區別
- 所有請求時間限制