ブログに戻る

Node.jsアプリケーションにおけるプロキシ設定:コード例付きの完全ガイド

Node.jsにおけるプロキシ統合の詳細ガイド:基本設定から高度なIPローテーション技術やエラーハンドリングまで。

📅2026年2月14日
```html

Node.jsアプリケーションを開発する際、パース、オートメーション、またはAPIとの連携のためにプロキシサーバーを使用する必要が生じることがよくあります。これにより、地理的制限を回避し、負荷を分散し、IPによるブロックを避けることができます。このガイドでは、Node.jsにおけるプロキシの設定方法を基本から高度な技術まで、IPのローテーションとエラーハンドリングを含めて解説します。

Node.jsにおけるプロキシの基本概念

Node.jsにおけるプロキシサーバーは、アプリケーションとターゲットサーバーの間の仲介者として機能します。プロキシを介してHTTPリクエストを送信すると、アプリケーションはまずプロキシサーバーに接続し、その後プロキシがリクエストを最終アドレスに転送します。これにより、サーバーの実際のIPアドレスを隠し、プロキシのIPアドレスを使用することができます。

Node.jsには、使用するHTTPリクエストライブラリに応じてプロキシを操作するためのいくつかの基本的な方法があります。最も人気のあるオプションは以下の通りです:

  • 組み込みのhttp/httpsモジュール — 追加の依存関係なしの基本機能
  • Axios — 便利なAPIとPromiseサポートを備えた人気のライブラリ
  • Got — TypeScriptサポートを備えた現代的な代替手段
  • node-fetch — Node.js用のFetch APIの実装
  • request — 廃止されたが未だに使用されているライブラリ(新しいプロジェクトには推奨されません)

プロキシサーバーはさまざまなプロトコルをサポートしています。Node.jsで最も一般的に使用されるのは以下のプロトコルです:

プロトコル 説明 用途
HTTP 暗号化されていない接続のための基本プロトコル パース、SSLなしでのAPI操作
HTTPS SSL/TLS暗号化をサポートするプロキシ 安全な接続、保護されたAPIとの操作
SOCKS5 あらゆるタイプのトラフィックに対応する汎用プロトコル WebSocket、UDP、複雑なシナリオ

パースやオートメーションのタスクでは、開発者はしばしばレジデンシャルプロキシを使用します。これは、実際の家庭ユーザーのIPアドレスを持ち、ターゲットサイトからのブロックに遭遇することが少ないためです。

組み込みのhttp/httpsモジュールを使用したプロキシの設定

Node.jsは、HTTPリクエストを処理するために組み込みのhttpおよびhttpsモジュールを提供します。プロキシを接続するには、http-proxy-agentまたはhttps-proxy-agentライブラリを使用できます。

まず、必要なパッケージをインストールします:

npm install http-proxy-agent https-proxy-agent

組み込みモジュールを使用したHTTPプロキシの例:

const http = require('http');
const { HttpProxyAgent } = require('http-proxy-agent');

// プロキシの設定
const proxyUrl = 'http://username:password@proxy-server.com:8080';
const agent = new HttpProxyAgent(proxyUrl);

// リクエストのオプション
const options = {
  hostname: 'api.example.com',
  path: '/endpoint',
  method: 'GET',
  agent: agent,
  headers: {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
  }
};

// リクエストの実行
const req = http.request(options, (res) => {
  let data = '';
  
  res.on('data', (chunk) => {
    data += chunk;
  });
  
  res.on('end', () => {
    console.log('Response:', data);
  });
});

req.on('error', (error) => {
  console.error('Request failed:', error.message);
});

req.end();

HTTPS接続にはhttps-proxy-agentを使用します:

const https = require('https');
const { HttpsProxyAgent } = require('https-proxy-agent');

const proxyUrl = 'http://username:password@proxy-server.com:8080';
const agent = new HttpsProxyAgent(proxyUrl);

const options = {
  hostname: 'api.example.com',
  path: '/secure-endpoint',
  method: 'GET',
  agent: agent
};

https.get(options, (res) => {
  let data = '';
  
  res.on('data', (chunk) => {
    data += chunk;
  });
  
  res.on('end', () => {
    console.log('Secure response:', data);
  });
}).on('error', (error) => {
  console.error('HTTPS request failed:', error.message);
});

このアプローチはリクエストに対する最大の制御を提供しますが、Promiseやエラー処理のためにより多くのコードが必要です。ほとんどのタスクには、専門のライブラリを使用する方が便利です。

Axiosライブラリでのプロキシの操作

AxiosはNode.jsにおけるHTTPリクエストのための最も人気のあるライブラリの一つです。プロキシの設定のための便利なAPIを提供し、Promiseを自動的に処理します。

Axiosのインストール:

npm install axios

Axiosでのプロキシの基本設定は以下のようになります:

const axios = require('axios');

// 方法1:リクエストの設定でプロキシを設定
axios.get('https://api.example.com/data', {
  proxy: {
    protocol: 'http',
    host: 'proxy-server.com',
    port: 8080,
    auth: {
      username: 'your-username',
      password: 'your-password'
    }
  }
})
.then(response => {
  console.log('Data:', response.data);
})
.catch(error => {
  console.error('Error:', error.message);
});

同じプロキシ設定を何度も使用する場合は、事前に設定された構成でAxiosのインスタンスを作成するのが便利です:

const axios = require('axios');

// プロキシ設定のインスタンスを作成
const axiosWithProxy = axios.create({
  proxy: {
    protocol: 'http',
    host: 'proxy-server.com',
    port: 8080,
    auth: {
      username: 'your-username',
      password: 'your-password'
    }
  },
  timeout: 10000,
  headers: {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
  }
});

// インスタンスの使用
async function fetchData() {
  try {
    const response = await axiosWithProxy.get('https://api.example.com/data');
    console.log('Response:', response.data);
    return response.data;
  } catch (error) {
    console.error('Request failed:', error.message);
    throw error;
  }
}

fetchData();

HTTPSプロキシをCONNECTメソッドで使用するには、追加のエージェントを使用できます:

const axios = require('axios');
const { HttpsProxyAgent } = require('https-proxy-agent');

const proxyUrl = 'http://username:password@proxy-server.com:8080';
const httpsAgent = new HttpsProxyAgent(proxyUrl);

const axiosInstance = axios.create({
  httpsAgent: httpsAgent,
  timeout: 15000
});

// 使用
axiosInstance.get('https://api.example.com/secure-data')
  .then(response => console.log(response.data))
  .catch(error => console.error(error.message));

Axiosは自動的にリダイレクトを処理し、ロギングやエラーハンドリングのためのインターセプターをサポートしているため、プロキシを活発に使用するプロジェクトに最適な選択肢です。

gotとnode-fetchでのプロキシの設定

GotはAxiosの現代的な代替手段で、TypeScriptの優れたサポートと高度なエラーハンドリング機能を提供します。Node-fetchはNode.js用の標準Fetch APIを実装しています。

Gotでのプロキシの操作

Gotと必要なエージェントのインストール:

npm install got https-proxy-agent

Gotでのプロキシ設定の例:

const got = require('got');
const { HttpsProxyAgent } = require('https-proxy-agent');

const proxyUrl = 'http://username:password@proxy-server.com:8080';
const agent = {
  https: new HttpsProxyAgent(proxyUrl)
};

// プロキシを使用したGotのインスタンスを作成
const gotWithProxy = got.extend({
  agent: agent,
  timeout: {
    request: 10000
  },
  retry: {
    limit: 3,
    methods: ['GET', 'POST']
  }
});

// 使用
async function fetchWithGot() {
  try {
    const response = await gotWithProxy('https://api.example.com/data');
    console.log('Response:', JSON.parse(response.body));
  } catch (error) {
    console.error('Got request failed:', error.message);
  }
}

fetchWithGot();

node-fetchでのプロキシの操作

Node-fetchはプロキシを使用するためにエージェントの明示的な設定が必要です:

npm install node-fetch https-proxy-agent
const fetch = require('node-fetch');
const { HttpsProxyAgent } = require('https-proxy-agent');

const proxyUrl = 'http://username:password@proxy-server.com:8080';
const agent = new HttpsProxyAgent(proxyUrl);

async function fetchWithProxy() {
  try {
    const response = await fetch('https://api.example.com/data', {
      agent: agent,
      headers: {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
      }
    });
    
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    
    const data = await response.json();
    console.log('Data:', data);
    return data;
  } catch (error) {
    console.error('Fetch failed:', error.message);
    throw error;
  }
}

fetchWithProxy();

Gotは、ボックスから豊富な機能を提供します(自動再試行、タイムアウト、エラーハンドリング)、一方でnode-fetchは標準のFetch APIに近く、ブラウザのJavaScriptに慣れた開発者に適しています。

socks-proxy-agentを使用したSOCKS5プロキシの接続

SOCKS5は、HTTP/HTTPSよりも低いレベルで動作する汎用プロキシプロトコルです。UDPやWebSocket接続を含むあらゆるタイプのトラフィックをサポートします。Node.jsでSOCKS5を使用するには、socks-proxy-agentライブラリを使用します。

必要なパッケージのインストール:

npm install socks-proxy-agent

様々なライブラリでSOCKS5プロキシを使用する例:

const { SocksProxyAgent } = require('socks-proxy-agent');
const https = require('https');

// 認証付きSOCKS5プロキシの設定
const proxyUrl = 'socks5://username:password@proxy-server.com:1080';
const agent = new SocksProxyAgent(proxyUrl);

const options = {
  hostname: 'api.example.com',
  path: '/endpoint',
  method: 'GET',
  agent: agent
};

https.get(options, (res) => {
  let data = '';
  
  res.on('data', (chunk) => {
    data += chunk;
  });
  
  res.on('end', () => {
    console.log('SOCKS5 response:', data);
  });
}).on('error', (error) => {
  console.error('SOCKS5 request failed:', error.message);
});

AxiosでのSOCKS5の使用:

const axios = require('axios');
const { SocksProxyAgent } = require('socks-proxy-agent');

const proxyUrl = 'socks5://username:password@proxy-server.com:1080';
const httpsAgent = new SocksProxyAgent(proxyUrl);
const httpAgent = new SocksProxyAgent(proxyUrl);

const axiosWithSocks = axios.create({
  httpAgent: httpAgent,
  httpsAgent: httpsAgent,
  timeout: 15000
});

async function fetchViaSocks5() {
  try {
    const response = await axiosWithSocks.get('https://api.example.com/data');
    console.log('Data via SOCKS5:', response.data);
    return response.data;
  } catch (error) {
    console.error('SOCKS5 request error:', error.message);
    throw error;
  }
}

fetchViaSocks5();

SOCKS5プロキシは、非標準プロトコルを扱う必要があるタスクや、最大限の柔軟性が必要な場合に特に有用です。多くのプロバイダーは、SOCKS5をサポートするモバイルプロキシを提供しており、モバイルAPIとの操作のためにモバイルトラフィックをエミュレートすることができます。

負荷分散のためのプロキシのローテーションの実装

大量のデータをパースしたり、1つのIPからのリクエスト数に制限があるAPIを操作する場合、プロキシのローテーションを使用する必要があります。これにより、複数のプロキシサーバー間でリクエストを分散し、ブロックを回避することができます。

プロキシのシンプルなローテーションの実装例:

const axios = require('axios');
const { HttpsProxyAgent } = require('https-proxy-agent');

class ProxyRotator {
  constructor(proxyList) {
    this.proxyList = proxyList;
    this.currentIndex = 0;
  }
  
  // サークル方式で次のプロキシを取得
  getNextProxy() {
    const proxy = this.proxyList[this.currentIndex];
    this.currentIndex = (this.currentIndex + 1) % this.proxyList.length;
    return proxy;
  }
  
  // ランダムなプロキシを取得
  getRandomProxy() {
    const randomIndex = Math.floor(Math.random() * this.proxyList.length);
    return this.proxyList[randomIndex];
  }
  
  // 現在のプロキシでAxiosインスタンスを作成
  createAxiosInstance(useRandom = false) {
    const proxyUrl = useRandom ? this.getRandomProxy() : this.getNextProxy();
    const agent = new HttpsProxyAgent(proxyUrl);
    
    return axios.create({
      httpsAgent: agent,
      timeout: 10000,
      headers: {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
      }
    });
  }
}

// プロキシのリスト
const proxyList = [
  'http://user1:pass1@proxy1.example.com:8080',
  'http://user2:pass2@proxy2.example.com:8080',
  'http://user3:pass3@proxy3.example.com:8080',
  'http://user4:pass4@proxy4.example.com:8080'
];

const rotator = new ProxyRotator(proxyList);

// ローテーションの使用
async function fetchWithRotation(url) {
  const axiosInstance = rotator.createAxiosInstance();
  
  try {
    const response = await axiosInstance.get(url);
    console.log('Success with proxy');
    return response.data;
  } catch (error) {
    console.error('Request failed:', error.message);
    throw error;
  }
}

// ローテーションを伴う大量パースの例
async function massiveParsing(urls) {
  const results = [];
  
  for (const url of urls) {
    try {
      const data = await fetchWithRotation(url);
      results.push({ url, success: true, data });
      
      // リクエスト間の遅延
      await new Promise(resolve => setTimeout(resolve, 1000));
    } catch (error) {
      results.push({ url, success: false, error: error.message });
    }
  }
  
  return results;
}

// パースの実行
const urlsToParse = [
  'https://api.example.com/data/1',
  'https://api.example.com/data/2',
  'https://api.example.com/data/3',
  'https://api.example.com/data/4',
  'https://api.example.com/data/5'
];

massiveParsing(urlsToParse)
  .then(results => console.log('Parsing results:', results))
  .catch(error => console.error('Parsing error:', error));

プロキシの状態を追跡し、動作しないものを自動的に除外するより高度な例:

class AdvancedProxyRotator {
  constructor(proxyList, maxFailures = 3) {
    this.proxyList = proxyList.map(url => ({
      url,
      failures: 0,
      active: true,
      lastUsed: null
    }));
    this.maxFailures = maxFailures;
    this.currentIndex = 0;
  }
  
  // アクティブなプロキシを取得
  getActiveProxy() {
    const activeProxies = this.proxyList.filter(p => p.active);
    
    if (activeProxies.length === 0) {
      throw new Error('No active proxies available');
    }
    
    // 最も長く使用されていないプロキシを検索
    const proxy = activeProxies.reduce((oldest, current) => {
      if (!oldest.lastUsed) return oldest;
      if (!current.lastUsed) return current;
      return current.lastUsed < oldest.lastUsed ? current : oldest;
    });
    
    proxy.lastUsed = Date.now();
    return proxy;
  }
  
  // プロキシを成功としてマーク
  markSuccess(proxyUrl) {
    const proxy = this.proxyList.find(p => p.url === proxyUrl);
    if (proxy) {
      proxy.failures = 0;
    }
  }
  
  // プロキシを失敗としてマーク
  markFailure(proxyUrl) {
    const proxy = this.proxyList.find(p => p.url === proxyUrl);
    if (proxy) {
      proxy.failures++;
      if (proxy.failures >= this.maxFailures) {
        proxy.active = false;
        console.warn(`Proxy ${proxyUrl} deactivated after ${proxy.failures} failures`);
      }
    }
  }
  
  // ローテーションでAxiosインスタンスを作成
  async createAxiosInstance() {
    const proxy = this.getActiveProxy();
    const agent = new HttpsProxyAgent(proxy.url);
    
    return {
      instance: axios.create({
        httpsAgent: agent,
        timeout: 10000
      }),
      proxyUrl: proxy.url
    };
  }
  
  // プロキシの統計を取得
  getStats() {
    return {
      total: this.proxyList.length,
      active: this.proxyList.filter(p => p.active).length,
      inactive: this.proxyList.filter(p => !p.active).length,
      proxies: this.proxyList.map(p => ({
        url: p.url.replace(/\/\/.*@/, '//***@'), // 認証情報を隠す
        active: p.active,
        failures: p.failures
      }))
    };
  }
}

// 高度なローテーターの使用
const advancedRotator = new AdvancedProxyRotator(proxyList);

async function fetchWithAdvancedRotation(url) {
  const { instance, proxyUrl } = await advancedRotator.createAxiosInstance();
  
  try {
    const response = await instance.get(url);
    advancedRotator.markSuccess(proxyUrl);
    return response.data;
  } catch (error) {
    advancedRotator.markFailure(proxyUrl);
    throw error;
  }
}

// 定期的な統計出力
setInterval(() => {
  console.log('Proxy stats:', advancedRotator.getStats());
}, 30000);

このシステムは、動作しないプロキシを自動的にローテーションから除外し、アクティブなサーバー間で負荷を均等に分散します。これは、大量のデータを扱う際に非常に重要です。

エラーハンドリングと自動プロキシ切り替え

プロキシを使用する際には、タイムアウト、接続の拒否、ターゲットサーバーからのブロックなどのエラーが避けられません。エラーを適切に処理し、別のプロキシに自動的に切り替えることで、アプリケーションの信頼性を高めることができます。

自動再試行とプロキシ切り替えを伴うシステムの実装例:

const axios = require('axios');
const { HttpsProxyAgent } = require('https-proxy-agent');

class ResilientProxyClient {
  constructor(proxyList, maxRetries = 3) {
    this.proxyList = proxyList;
    this.maxRetries = maxRetries;
    this.currentProxyIndex = 0;
  }
  
  // 次のプロキシを取得
  getNextProxy() {
    const proxy = this.proxyList[this.currentProxyIndex];
    this.currentProxyIndex = (this.currentProxyIndex + 1) % this.proxyList.length;
    return proxy;
  }
  
  // エラーのタイプを判定
  isRetryableError(error) {
    // 再試行すべきエラー
    const retryableCodes = ['ECONNRESET', 'ETIMEDOUT', 'ENOTFOUND', 'ECONNREFUSED'];
    const retryableStatuses = [408, 429, 500, 502, 503, 504];
    
    if (error.code && retryableCodes.includes(error.code)) {
      return true;
    }
    
    if (error.response && retryableStatuses.includes(error.response.status)) {
      return true;
    }
    
    return false;
  }
  
  // 自動再試行を伴うリクエストを実行
  async request(url, options = {}, attempt = 1) {
    const proxyUrl = this.getNextProxy();
    const agent = new HttpsProxyAgent(proxyUrl);
    
    const config = {
      ...options,
      httpsAgent: agent,
      timeout: 10000,
      headers: {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        ...options.headers
      }
    };
    
    try {
      console.log(`Attempt ${attempt}/${this.maxRetries} with proxy: ${proxyUrl.replace(/\/\/.*@/, '//***@')}`);
      const response = await axios.get(url, config);
      console.log(`Success on attempt ${attempt}`);
      return response.data;
    } catch (error) {
      console.error(`Attempt ${attempt} failed: ${error.message}`);
      
      // 再試行の上限に達した場合
      if (attempt >= this.maxRetries) {
        console.error(`Max retries (${this.maxRetries}) reached for ${url}`);
        throw error;
      }
      
      // 再試行しないエラーの場合
      if (!this.isRetryableError(error)) {
        console.error(`Non-retryable error: ${error.message}`);
        throw error;
      }
      
      // 再試行前の指数関数的遅延
      const delay = Math.min(1000 * Math.pow(2, attempt - 1), 10000);
      console.log(`Waiting ${delay}ms before retry...`);
      await new Promise(resolve => setTimeout(resolve, delay));
      
      // 次のプロキシで再帰的に再試行
      return this.request(url, options, attempt + 1);
    }
  }
  
  // エラーハンドリングを伴うURLのバッチ処理
  async batchRequest(urls, concurrency = 3) {
    const results = [];
    const queue = [...urls];
    const active = [];
    
    while (queue.length > 0 || active.length > 0) {
      // 同時実行の制限に達するまで新しいタスクを開始
      while (active.length < concurrency && queue.length > 0) {
        const url = queue.shift();
        const promise = this.request(url)
          .then(data => ({ url, success: true, data }))
          .catch(error => ({ url, success: false, error: error.message }))
          .finally(() => {
            const index = active.indexOf(promise);
            if (index > -1) active.splice(index, 1);
          });
        
        active.push(promise);
      }
      
      // いずれかのタスクが完了するのを待つ
      if (active.length > 0) {
        const result = await Promise.race(active);
        results.push(result);
      }
    }
    
    return results;
  }
}

// 使用
const proxyList = [
  'http://user1:pass1@proxy1.example.com:8080',
  'http://user2:pass2@proxy2.example.com:8080',
  'http://user3:pass3@proxy3.example.com:8080'
];

const client = new ResilientProxyClient(proxyList, 3);

// 単一リクエスト
client.request('https://api.example.com/data')
  .then(data => console.log('Data:', data))
  .catch(error => console.error('Final error:', error.message));

// バッチ処理
const urls = [
  'https://api.example.com/data/1',
  'https://api.example.com/data/2',
  'https://api.example.com/data/3',
  'https://api.example.com/data/4',
  'https://api.example.com/data/5'
];

client.batchRequest(urls, 3)
  .then(results => {
    const successful = results.filter(r => r.success).length;
    const failed = results.filter(r => !r.success).length;
    console.log(`Completed: ${successful} successful, ${failed} failed`);
    console.log('Results:', results);
  });

この実装には以下が含まれます:

  • エラー時に次のプロキシに自動的に切り替え
  • 再試行間の指数関数的遅延(1秒、2秒、4秒、8秒、最大10秒)
  • 再試行の決定のためのエラータイプの判定
  • バッチ処理時の同時実行の制御
  • デバッグのための詳細なロギング

ベストプラクティスとパフォーマンスの最適化

Node.jsアプリケーションでプロキシを使用する際は、安定性とパフォーマンスを確保するために以下の推奨事項に従うべきです:

1. 接続の管理

各リクエストのために新しいHTTPエージェントを作成するのではなく、再利用してください。これにより、接続の確立にかかるオーバーヘッドが減ります:

const { HttpsProxyAgent } = require('https-proxy-agent');

// 悪い例:各リクエストのためにエージェントを作成
async function badExample(url) {
  const agent = new HttpsProxyAgent(proxyUrl);
  return axios.get(url, { httpsAgent: agent });
}

// 良い例:エージェントを再利用
const agent = new HttpsProxyAgent(proxyUrl);
const axiosInstance = axios.create({
  httpsAgent: agent,
  httpAgent: agent
});

async function goodExample(url) {
  return axiosInstance.get(url);
}

2. タイムアウトの設定

アプリケーションがハングしないように、常に合理的なタイムアウトを設定してください:

const axiosInstance = axios.create({
  httpsAgent: agent,
  timeout: 10000, // 全体のタイムアウト
  // Gotのタイムアウトの詳細設定
  // timeout: {
  //   lookup: 1000,    // DNSルックアップ
  //   connect: 2000,   // プロキシへの接続
  //   secureConnect: 2000, // SSLハンドシェイク
  //   socket: 5000,    // ソケットの非アクティブ
  //   response: 3000,  // 最初のバイトの応答を待つ
  //   send: 10000,     // リクエストの送信
  //   request: 15000   // 全リクエスト
  // }
});

3. 同時実行の制御

過負荷を避けるために、同時リクエストの数を制限してください:

const pLimit = require('p-limit');

// 同時に5つのリクエストを制限
const limit = pLimit(5);

async function processUrls(urls) {
  const promises = urls.map(url => 
    limit(() => axiosInstance.get(url))
  );
  
  return Promise.allSettled(promises);
}

4. User-Agentのローテーション

プロキシのローテーションとUser-Agentのローテーションを組み合わせて、より高い匿名性を確保してください:

const userAgents = [
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
  'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0'
];

function getRandomUserAgent() {
  return userAgents[Math.floor(Math.random() * userAgents.length)];
}

async function fetchWithRandomUA(url) {
  return axiosInstance.get(url, {
    headers: {
      'User-Agent': getRandomUserAgent()
    }
  });
}

5. モニタリングとロギング

プロキシのパフォーマンスを追跡するためのモニタリングシステムを実装してください:

class ProxyMonitor {
  constructor() {
    this.stats = new Map();
  }
  
  recordRequest(proxyUrl, success, responseTime) {
    if (!this.stats.has(proxyUrl)) {
      this.stats.set(proxyUrl, {
        total: 0,
        success: 0,
        failed: 0,
        totalResponseTime: 0,
        avgResponseTime: 0
      });
    }
    
    const stat = this.stats.get(proxyUrl);
    stat.total++;
    
    if (success) {
      stat.success++;
      stat.totalResponseTime += responseTime;
      stat.avgResponseTime = stat.totalResponseTime / stat.success;
    } else {
      stat.failed++;
    }
  }
  
  getReport() {
    const report = [];
    
    this.stats.forEach((stat, proxyUrl) => {
      report.push({
        proxy: proxyUrl.replace(/\/\/.*@/, '//***@'),
        successRate: ((stat.success / stat.total) * 100).toFixed(2) + '%',
        avgResponseTime: stat.avgResponseTime.toFixed(0) + 'ms',
        total: stat.total,
        success: stat.success,
        failed: stat.failed
      });
    });
    
    return report;
  }
}

const monitor = new ProxyMonitor();

// モニタリング付きリクエストのラッパー
async function monitoredRequest(url, proxyUrl) {
  const startTime = Date.now();
  
  try {
    const response = await axiosInstance.get(url);
    const responseTime = Date.now() - startTime;
    monitor.recordRequest(proxyUrl, true, responseTime);
    return response.data;
  } catch (error) {
    const responseTime = Date.now() - startTime;
    monitor.recordRequest(proxyUrl, false, responseTime);
    throw error;
  }
}

// 定期的なレポート
setInterval(() => {
  console.table(monitor.getReport());
}, 60000);

6. プロキシのタイプの選択

タスクに応じてプロキシのタイプを選択してください:

タスク 推奨タイプ 理由
公開データの大量パース データセンタープロキシ 高速、低コスト
ソーシャルメディアや保護されたプラットフォームでの操作 レジデンシャルプロキシ 実際のIP、ブロックのリスクが低い
モバイルトラフィックのエミュレーション モバイルプロキシ モバイルオペレーターのIP
非標準プロトコルでの操作 SOCKS5プロキシ あらゆるトラフィックをサポート

高い匿名性と最小限のブロックリスクを必要とするタスクには、レジデンシャルプロキシの使用をお勧めします。大量データの高速パースには、データセンタープロキシが適しています。

7. 認証情報のセキュリティ

プロキシの認証情報をコードに保存しないでください。環境変数を使用してください:

// .envファイル
PROXY_HOST=proxy-server.com
PROXY_PORT=8080
PROXY_USERNAME=your-username
PROXY_PASSWORD=your-password

// コード内で
require('dotenv').config();

const proxyUrl = `http://${process.env.PROXY_USERNAME}:${process.env.PROXY_PASSWORD}@${process.env.PROXY_HOST}:${process.env.PROXY_PORT}`;

// またはプロキシリストの場合
const proxyList = process.env.PROXY_LIST.split(',').map(proxy => proxy.trim());

結論

Node.jsアプリケーションにおけるプロキシの設定は、パース、オートメーション、外部APIとの統合に取り組む開発者にとって重要なスキルです。このガイドでは、組み込みモジュールを使用した基本的な設定から、ローテーション、エラーハンドリング、モニタリングを伴う高度な技術まで、プロキシの操作方法をすべて解説しました。

覚えておくべき重要なポイント:

  • タスクに応じてHTTPリクエストライブラリを選択してください:Axiosは汎用性があり、GotはTypeScriptプロジェクトに適しており、node-fetchはブラウザAPIとの互換性があります。
  • 非標準プロトコルを扱う場合や最大限の柔軟性が必要な場合はSOCKS5プロキシを使用してください。
  • 負荷分散とブロック回避のためにプロキシのローテーションを実装してください。
  • 自動再試行とプロキシ切り替えを伴うエラーハンドリングシステムを導入してください。
  • プロキシのパフォーマンスをモニタリングし、動作しないものを自動的に除外してください。
  • HTTPエージェントを再利用し、合理的なタイムアウトを設定してください。
  • 認証情報をコード内に保存せず、環境変数を使用してください。

Node.jsアプリケーションのプロキシを選択する際は、タスクの特性を考慮してください。保護されたプラットフォームのパースや、IPの評判に敏感なAPIとの操作には、レジデンシャルプロキシの使用をお勧めします。これにより、実際の家庭ユーザーのIPアドレスを使用することで、高い匿名性と最小限のブロックリスクを確保できます。

```