Guzzle로 프록시 설정하는 방법

Guzzle과 프록시를 활용하여 웹 스크래핑 문제를 해결하십시오. PHP 7.2.5 이상과 Composer가 설정되었는지 확인한 후, 프록시 구성을 위해 Guzzle을 통합하십시오.
2 분 읽기
Setting a proxy in Guzzle blog image

Guzzle 사용 시 프록시는 클라이언트 애플리케이션과 대상 웹 서버를 연결하는 중개 서버 역할을 합니다. 요청을 원하는 서버로 전달하고 서버의 응답을 클라이언트에 반환합니다. 또한 프록시는 웹 스크래핑 활동을 차단하거나 특정 웹사이트 접근을 제한하는 IP 기반 제한을 우회하는 데 유용하며, 대상 서버로의 직접 요청 횟수를 줄이기 위해 서버 응답을 캐싱하는 등의 이점을 제공합니다.

이 소개에서는 Guzzle과 함께 프록시를 효과적으로 활용하기 위한 필수 사항을 설명합니다.

시작하기 요구 사항 – 통합 방법

진행하기 전에 시스템에 PHP 버전 7.2.5 이상과 Composer가 설치되어 있는지 확인하십시오. PHP를 사용한 웹 스크래핑에 대한 기본적인 이해도 이 가이드를 따라가는 데 도움이 될 것입니다. 프로젝트용 새 디렉터리를 생성하고 Composer를 사용하여 그 안에 Guzzle를 설치하는 것으로 시작하십시오:

composer require guzzlehttp/guzzle

다음으로 새로 생성한 디렉터리 내에 PHP 파일을 만들고 Composer의 자동 로더를 포함시켜 진행합니다:

<?php
// Composer 자동 로더 로드
require 'vendor/autoload.php';

이제 프록시 설정을 구성할 준비가 되었습니다.

Guzzle에서 프록시 활용하기

이 섹션에서는 프록시를 활용하여 Guzzle로 요청을 발행하고 인증하는 방법을 보여줍니다. 먼저 프록시 정보를 확인하고, 활성화되었으며 다음 형식을 따르는지 확인하세요: <프록시_프로토콜>://<프록시_사용자_이름>:<프록시_비밀번호>@<프록시_호스트>:<프록시_포트>.

핵심 포인트: Guzzle은 request-options 또는 미들웨어를 통해 프록시 사용을 지원합니다. 간단하고 변경되지 않은 프록시 설정에는 request-options가 적합합니다. 반면 미들웨어는 초기 설정이 더 필요하지만 향상된 유연성과 제어 기능을 제공합니다.

두 가지 접근법을 모두 살펴보겠습니다. 먼저 요청 옵션부터 시작하며, 설정을 위해 Guzzle의 Client 및 RequestOptions 클래스를 가져와야 합니다.

방법 A: request-options로 Guzzle 프록시 설정하기

request-options로 프록시를 설정하려면 먼저 Guzzle의 Client 및 RequestOptions 클래스를 임포트하세요:

use GuzzleHttpClient;
use GuzzleHttpRequestOptions;

그런 다음 대상 URL과 사용할 모든 프록시를 연관 배열로 정의합니다:

# 요청 대상 URL
$targetUrl = 'https://lumtest.com/myip.json';

# 프록시
$proxies = [
    'http'  => 'http://USERNAME:[email protected]:22225',
    'https' => 'http://USERNAME:[email protected]:22225',
];

지정된 대상 URL인 lumtest는 해당 주소로 GET 요청을 보내는 모든 클라이언트의 IP 주소를 반환하도록 설계되었습니다. 이 설정으로 Guzzle은 HTTP 및 HTTPS 트래픽을 모두 관리하며, 지정된 HTTP 및 HTTPS 프록시를 통해 각각 라우팅할 수 있습니다.

다음으로, Guzzle 클라이언트 인스턴스를 생성하고, 이전에 정의한 프록시들을 Guzzle 구성의 proxy 옵션에 할당하여 통합합니다.

$client = new Client([
RequestOptions::PROXY => $proxies,
RequestOptions::VERIFY => false, # SSL 인증서 검증 비활성화
RequestOptions::TIMEOUT => 30, # 30초 타임아웃
]);

프록시 서버는 종종 SSL 검증에 문제가 발생하므로, 이 설정에서는 verify 옵션을 통해 검증을 비활성화합니다. 또한 타임아웃 설정은 각 요청의 지속 시간을 최대 30초로 제한합니다. 이 구성에 따라 요청을 실행하고 결과 응답을 표시합니다.

try {
$body = $client->get($targetUrl)->getBody();
echo $body->getContents();
} catch (Exception $e) {
echo $e->getMessage();
}

지금쯤이면 PHP 스크립트는 다음과 비슷할 것입니다:

'http://USERNAME:[email protected]:22225', 'https' => 'http://USERNAME:[email protected]:22225', ]; $client = new Client([ RequestOptions::PROXY => $proxies, RequestOptions::VERIFY => false, # SSL 인증서 검증 비활성화 RequestOptions::TIMEOUT => 30, # 30초 시간 제한 ]); try { $body = $client->get($targetUrl)->getBody(); echo $body->getContents(); } catch (Exception $e) { echo $e->getMessage(); } ?>

php .php 명령어로 스크립트를 실행하면 아래 예시와 유사한 출력을 받게 됩니다:

{"ip":"212.80.220.187","country":"IE","asn":{"asnum":9009,"org_name":"M247 Europe SRL"},"geo":{"city":"Dublin","region":"L","region_name":"Leinster","postal_code":"D12","latitude":53.323,"longitude":-6.3159,"tz":"Europe/Dublin","lum_city":"dublin","lum_region":"l"}}

훌륭합니다! ip 키의 값은 lumtest에 요청을 시작한 클라이언트의 IP 주소와 일치합니다. 이 경우, 설정하신 프록시를 반영해야 합니다.

접근법 B: 미들웨어 활용

Guzzle HTTP 프록시 설정을 위한 미들웨어 사용은 첫 번째 방법과 유사한 패턴을 따릅니다. 유일한 차이점은 프록시 미들웨어를 생성하고 기본 핸들러 스택에 통합하는 데 있습니다.

먼저, 다음과 같이 임포트(import)를 수정하세요:

# ...
use PsrHttpMessageRequestInterface;
use GuzzleHttpHandlerStack;
# ...

그런 다음 $proxies 배열 바로 다음에 다음 코드를 삽입하여 프록시 미들웨어를 설정합니다. 이 미들웨어는 모든 요청을 가로채고 프록시를 적절히 구성합니다.

function proxy_middleware(array $proxies) 
{
    return function (callable $handler) use ($proxies) {
        return function (RequestInterface $request, array $options) use ($handler, $proxies) {
            # 요청 옵션에 프록시 추가
            $options[RequestOptions::PROXY] = $proxies; 
            return $handler($request, $options);
        };
    };
}

이제 미들웨어를 기본 핸들러 스택에 통합하고 스택을 포함시켜 Guzzle 클라이언트를 새로 고칠 수 있습니다:

$stack = HandlerStack::create();
$stack->push(proxy_middleware($proxies));

$client = new Client([
    'handler' => $stack,
    RequestOptions::VERIFY => false, # SSL 인증서 검증 비활성화
    RequestOptions::TIMEOUT => 30, # 30초 타임아웃
]);

PHP 스크립트는 다음과 같아야 합니다:

<?php
require 'vendor/autoload.php';
use GuzzleHttpClient;
use GuzzleHttpRequestOptions;
use PsrHttpMessageRequestInterface;
use GuzzleHttpHandlerStack;
# 요청 대상
$targetUrl = 'https://lumtest.com/myip.json';

# 프록시 설정
$proxies = [
    'http'  => 'http://USERNAME:[email protected]:22225',
    'https' => 'http://USERNAME:[email protected]:22225',
];
function proxy_middleware(array $proxies) 
{
    return function (callable $handler) use ($proxies) {
        return function (RequestInterface $request, array $options) use ($handler, $proxies) {
            # 요청 옵션에 프록시 추가
            $options[RequestOptions::PROXY] = $proxies; 
            return $handler($request, $options);
        };
    };
}

$stack = HandlerStack::create();
$stack->push(proxy_middleware($proxies));

$client = new Client([
    'handler' => $stack,
    RequestOptions::VERIFY => false, # SSL 인증서 검증 비활성화
    RequestOptions::TIMEOUT => 30, # 30초 타임아웃
]);

try {
    $body = $client->get($targetUrl)->getBody();
    echo $body->getContents();
} catch (Exception $e) {
    echo $e->getMessage();
}

?>

PHP 스크립트를 다시 실행하면 다른 방법과 유사한 결과를 얻을 수 있습니다.

Guzzle로 로테이팅 프록시 구현은 IP 주소를 자주 변경하는 프록시 서버를 활용하는 것입니다. 이 접근 방식은 각 요청이 서로 다른 IP에서 발생하므로 단일 출처에서 발생하는 봇을 식별하기 어렵게 만들어 IP 차단을 우회하는 데 도움이 됩니다.

먼저 Guzzle로 회전 프록시를 구현해 보겠습니다. Bright Data의 프록시 서비스를 사용하면 매우 간단합니다. 예를 들어:

function get_random_proxies(): array {
    // 세션 식별자 이전의 기본 프록시 URL
    $baseProxyUrl = 'http://USERNAME-session-';

   
    $sessionSuffix = rand(1000, 9999); // 1000에서 9999 사이의 무작위 정수
    $proxyCredentials = ':[email protected]:22225';

    $httpProxy = $baseProxyUrl . $sessionSuffix . $proxyCredentials;
    $httpsProxy = $baseProxyUrl . $sessionSuffix . $proxyCredentials;


    $proxies = [
        'http'  => $httpProxy,
        'https' => $httpsProxy,
    ];

    return $proxies;
}

이제 원하는 함수를 추가하고 호출합니다:

function rotating_proxy_request(string $http_method, string $targetUrl, int $max_attempts = 3): string
{
    $response = null;
    $attempts = 1;

    while ($attempts <= $max_attempts) {
        $proxies = get_random_proxies();
        echo "프록시 사용: ".json_encode($proxies).PHP_EOL;
        $client = new Client([
            RequestOptions::PROXY => $proxies,
            RequestOptions::VERIFY => false, # SSL 인증서 검증 비활성화
            RequestOptions::TIMEOUT => 30, # 30초 타임아웃
        ]);
        try {
            $body = $client->request(strtoupper($http_method), $targetUrl)->getBody();
            $response = $body->getContents();
            break;
        } catch (Exception $e) {
            echo $e->getMessage().PHP_EOL;
            echo "시도 ".$attempts." 번 실패!".PHP_EOL;
            if ($attempts < $max_attempts) {
                echo "새로운 프록시로 재시도".PHP_EOL;
            }
            $attempts += 1;
        }
    }
    return $response;
}

$response = rotating_proxy_request('get', 'https://lumtest.com/myip.json');

echo $response;

전체 PHP 스크립트:

<?php
# composer의 자동 로더
require 'vendor/autoload.php';

use GuzzleHttpClient;
use GuzzleHttpRequestOptions;

function get_random_proxies(): array {
    // 세션 식별자 이전의 기본 프록시 URL
    $baseProxyUrl = 'http://USERNAME-session-';

    // 세션 ID 접미사 및 프록시 인증 정보
    $sessionSuffix = rand(1000, 9999); // 1000과 9999 사이의 난수 정수
    $proxyCredentials = ':[email protected]:22225';

    // 무작위 세션 ID로 전체 프록시 URL 조립
    $httpProxy = $baseProxyUrl . $sessionSuffix . $proxyCredentials;
    $httpsProxy = $baseProxyUrl . $sessionSuffix . $proxyCredentials;

    // 프록시 패키징 및 반환
    $proxies = [
        'http'  => $httpProxy,
        'https' => $httpsProxy,
    ];

    return $proxies;
}


function rotating_proxy_request(string $http_method, string $targetUrl, int $max_attempts = 3): string
{
    $response = null;
    $attempts = 1;

    while ($attempts <= $max_attempts) {
        $proxies = get_random_proxies();
        echo "프록시 사용: ".json_encode($proxies).PHP_EOL;
        $client = new Client([
            RequestOptions::PROXY => $proxies,
            RequestOptions::VERIFY => false, # SSL 인증서 검증 비활성화
            RequestOptions::TIMEOUT => 30, # 30초 타임아웃
        ]);
        try {
            $body = $client->request(strtoupper($http_method), $targetUrl)->getBody();
            $response = $body->getContents();
            break;
        } catch (Exception $e) {
            echo $e->getMessage().PHP_EOL;
            echo "시도 ".$attempts." 번 실패!".PHP_EOL;
            if ($attempts < $max_attempts) {
                echo "새로운 프록시로 재시도 중".PHP_EOL;
            }
            $attempts += 1;
        }
    }
    return $response;
}

$response = rotating_proxy_request('get', 'https://lumtest.com/myip.json');

echo $response;

결론

이 가이드에서는 Guzzle에 프록시를 통합하는 데 필요한 단계를 다루었습니다. 여러분은 다음을 배웠습니다:

  • Guzzle 작업 시 프록시 활용의 기본 원리.
  • 회전 프록시 시스템 구현 전략.

Bright Data는 API 호출을 통해 접근 가능한 신뢰할 수 있는 로테이팅 프록시 서비스를 제공하며, 봇 방지 조치를 우회하도록 설계된 고급 기능을 통해 스크래핑 작업의 효율성을 높여줍니다.