Как настроить прокси-сервер для Guzzle

Решайте проблемы с веб-парсингом с помощью Guzzle и прокси-серверов. Убедитесь, что PHP 7.2.5+ и Composer установлены, а затем интегрируйте Guzzle для настройки прокси-сервера.
1 min read
Setting a proxy in Guzzle blog image

При использовании Guzzle прокси-сервер выступает в качестве промежуточного сервера, соединяющего клиентское приложение с целевым веб-сервером. Это облегчает отправку запросов на нужный сервер и возвращает ответ сервера клиенту. Кроме того, прокси-серверы важны для обхода ограничений по IP-адресу, которые могут блокировать операции по веб-парсингу или ограничивать доступ к определенным веб-сайтам, а также предоставляют такие преимущества, как кэширование ответов сервера для сокращения количества прямых запросов к целевому серверу.

В этом введении описаны основные принципы эффективного использования прокси-сервера c Guzzle.

Требования для начала работы — как выполнить интеграцию

Прежде чем продолжить, убедитесь, что в вашей системе установлен PHP версии 7.2.5 или выше, а также Composer. Кроме того, для выполнения указаний этого руководства будет полезно знание основ веб-парсинга с помощью PHP. Начните с создания нового каталога для своего проекта и используйте Composer для установки в него Guzzle:

composer require guzzlehttp/guzzle

Затем создайте PHP-файл в новой папке и включите автозагрузчик Composer, чтобы продолжить:

<?php
// Load Composer's autoloader
require 'vendor/autoload.php';

Теперь можно настроить параметры прокси-сервера.

Использование прокси-сервера с Guzzle

В этом разделе показано, как отправить запрос через Guzzle с помощью прокси-сервера и аутентифицировать его. Сначала получите исходные сведения о прокси-серверах и убедитесь, что они активны и соответствуют формату: ://:@:.

Важная информация: Guzzle позволяет использовать прокси-сервер с помощью параметра request-options или промежуточного ПО. Для простых и неизменных настроек прокси-сервера подойдет request-options. И наоборот, промежуточное ПО обеспечивает повышенную гибкость и контроль, хотя требует приложить больше усилий для начальной настройки.

Мы рассмотрим оба способа, начиная с опций запроса, включая импорт классов Guzzle Client и RequestOptions для установки.

Способ A. Установка прокси-сервера Guzzle с помощью request-options

Чтобы настроить прокси-сервер с использованием request-options, начните с импорта классов Guzzle Client и RequestOptions:

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;

Затем определите целевой URL-адрес и ассоциативный массив всех прокси, которые будете использовать:

# make request to
$targetUrl = 'https://lumtest.com/myip.json';

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

Указанный целевой URL-адрес, lumtest, предназначен для возврата IP-адреса любого клиента, отправившего ему запрос GET. Эта настройка позволяет Guzzle управлять трафиком HTTP и HTTPS, направляя его соответствующим образом через указанные прокси-серверы HTTP и HTTPS.

Затем мы запустим экземпляр клиента Guzzle, включив ранее заданные прокси-серверы, присвоив им параметр proxy («прокси-сервер») в конфигурации Guzzle.

$client = new Client([
RequestOptions::PROXY => $proxies,
RequestOptions::VERIFY => false, # disable SSL certificate validation
RequestOptions::TIMEOUT => 30, # timeout of 30 seconds
]);

Поскольку на прокси-серверах часто возникают проблемы с проверкой SSL, в этой настройке проверка отключена с помощью параметра verify («проверка»). Кроме того, настройка timeout («тайм-аут») ограничивает продолжительность каждого запроса максимум тридцатью секундами. В соответствии с этой конфигурацией мы выполним запрос и отобразим полученный ответ.

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, # disable SSL certificate validation RequestOptions::TIMEOUT => 30, # timeout of 30 seconds ]); 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 соответствует IP-адресу клиента, инициировавшему запрос на lumtest. В данном случае в нем должны быть отражены настроенные вами прокси-серверы.

Способ Б. Использование промежуточного ПО

Использование промежуточного ПО для настройки прокси-сервера HTTP в Guzzle осуществляется в порядке, аналогичному порядку действий в способе А. Единственное отличие заключается в создании и включении промежуточного ПО прокси-сервера в стек обработчиков по умолчанию.

Для начала настройте импорт следующим образом:

# ...
use Psr\Http\Message\RequestInterface;
use GuzzleHttp\HandlerStack;
# ...

Затем создайте промежуточное ПО для прокси-сервера, вставив следующий код сразу после массива $proxies. Это промежуточное ПО будет перехватывать все запросы и соответствующим образом настраивать прокси-серверы.

function proxy_middleware(array $proxies) 
{
    return function (callable $handler) use ($proxies) {
        return function (RequestInterface $request, array $options) use ($handler, $proxies) {
            # add proxy to request option
            $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, # disable SSL certificate validation
    RequestOptions::TIMEOUT => 30, # timeout of 30 seconds
]);

Ваш PHP-скрипт должен выглядеть следующим образом:

<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
use Psr\Http\Message\RequestInterface;
use GuzzleHttp\HandlerStack;
# make request to
$targetUrl = 'https://lumtest.com/myip.json';

# proxies
$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) {
            # add proxy to request option
            $options[RequestOptions::PROXY] = $proxies; 
            return $handler($request, $options);
        };
    };
}

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

$client = new Client([
    'handler' => $stack,
    RequestOptions::VERIFY => false, # disable SSL certificate validation
    RequestOptions::TIMEOUT => 30, # timeout of 30 seconds
]);

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 {
    // Base proxy URL before the session identifier
    $baseProxyUrl = 'http://USERNAME-session-';

   
    $sessionSuffix = rand(1000, 9999); // Random integer between 1000 and 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 "Using proxy: ".json_encode($proxies).PHP_EOL;
        $client = new Client([
            RequestOptions::PROXY => $proxies,
            RequestOptions::VERIFY => false, # disable SSL certificate validation
            RequestOptions::TIMEOUT => 30, # timeout of 30 seconds
        ]);
        try {
            $body = $client->request(strtoupper($http_method), $targetUrl)->getBody();
            $response = $body->getContents();
            break;
        } catch (\Exception $e) {
            echo $e->getMessage().PHP_EOL;
            echo "Attempt ".$attempts." failed!".PHP_EOL;
            if ($attempts < $max_attempts) {
                echo "Retrying with a new proxy".PHP_EOL;
            }
            $attempts += 1;
        }
    }
    return $response;
}

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

echo $response;

Вот полный PHP-скрипт:

<?php
# composer's autoloader
require 'vendor/autoload.php';

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;

function get_random_proxies(): array {
    // Base proxy URL before the session identifier
    $baseProxyUrl = 'http://USERNAME-session-';

    // Session ID suffix and proxy credentials
    $sessionSuffix = rand(1000, 9999); // Random integer between 1000 and 9999
    $proxyCredentials = ':[email protected]:22225';

    // Assemble the full proxy URLs with the randomized session ID
    $httpProxy = $baseProxyUrl . $sessionSuffix . $proxyCredentials;
    $httpsProxy = $baseProxyUrl . $sessionSuffix . $proxyCredentials;

    // Package and return the proxies
    $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 "Using proxy: ".json_encode($proxies).PHP_EOL;
        $client = new Client([
            RequestOptions::PROXY => $proxies,
            RequestOptions::VERIFY => false, # disable SSL certificate validation
            RequestOptions::TIMEOUT => 30, # timeout of 30 seconds
        ]);
        try {
            $body = $client->request(strtoupper($http_method), $targetUrl)->getBody();
            $response = $body->getContents();
            break;
        } catch (\Exception $e) {
            echo $e->getMessage().PHP_EOL;
            echo "Attempt ".$attempts." failed!".PHP_EOL;
            if ($attempts < $max_attempts) {
                echo "Retrying with a new proxy".PHP_EOL;
            }
            $attempts += 1;
        }
    }
    return $response;
}

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

echo $response;

Заключение

В этом руководстве мы рассмотрели необходимые шаги по интеграции прокси-серверов с Guzzle. Вы узнали:

  • Основы использования прокси-сервера при работе с Guzzle.
  • Стратегии внедрения системы ротируемых прокси-серверов.

Bright Data предлагает надежный сервис ротируемых прокси-серверов, доступный с помощью вызовов API, а также продвинутые функции, позволяющие обойти меры по борьбе с ботами и повысить эффективность ваших усилий по парсингу.