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