パーサーを作成したり、データ収集を自動化したり、IP制限を回避したりする場合、PHPでプロキシは必須です。このガイドでは、組み込みのcURLと人気のあるライブラリGuzzle HTTP Clientの2つの主要なツールを取り上げ、すぐにプロジェクトで使用できるコードの例を示します。
PHPプロジェクトにおけるプロキシの必要性
PHPはサーバー自動化のための最も一般的な言語の1つであり、プロキシを必要とするタスクは常に存在します。以下は、プロキシが必要な主なシナリオです:
- ウェブサイトやマーケットプレイスのパース — Wildberries、Ozon、Avito、AliExpressは、数十のリクエストの後にIPをブロックします。プロキシを使用すると、異なるアドレス間で負荷を分散し、403/429を回避できます。
- 地理的に依存するリソースからのデータ収集 — 価格、検索エンジンの結果、コンテンツは国によって異なる場合があります。必要な地理的位置のプロキシがこの問題を解決します。
- レート制限の回避 — 多くのAPIは1つのIPからのリクエスト数を制限しています。プロキシのローテーションにより、これらの制限を回避できます。
- 地理的に依存するコンテンツのテスト — オフィスを出ずに、異なる国のユーザー向けにサイトがどのように見えるかを確認します。
- 自動化における匿名性 — 外部リソースへの大量リクエスト時にサーバーの実際のIPを隠します。
- 競合の監視 — 競合のウェブサイトから価格、品揃え、プロモーションを定期的に収集し、禁止されるリスクを回避します。
PHPでは、HTTPリクエストに対して主に2つのツールが使用されます: 組み込みの拡張機能cURLとライブラリGuzzle HTTP Clientです。どちらもHTTP、HTTPS、SOCKS4、SOCKS5プロキシをサポートしています — 各々を詳しく見ていきましょう。
PHPに適したプロキシの種類
コードを書く前に、どのタイプのプロキシがあなたのタスクに適しているかを理解することが重要です。異なるタイプは、速度、信頼性、匿名性の程度において異なる特性を持っています。
| プロキシの種類 | 速度 | 匿名性 | 最適な用途 |
|---|---|---|---|
| データセンターのプロキシ | 非常に高い | 中程度 | 厳しいアンチボットシステムのないパース、APIリクエスト |
| 住宅用プロキシ | 中程度 | 高い | 保護されたウェブサイトのパース、マーケットプレイス、地理データ |
| モバイルプロキシ | 中程度 | 最大 | 厳しいアンチボット保護のあるサイト、ソーシャルネットワーク |
WildberriesやOzonのようなマーケットプレイスからデータをパースするためのほとんどのタスクには、住宅用プロキシが最適な選択です — それらのIPは実際の家庭ユーザーに属しているため、リクエストは通常のブラウザトラフィックとほとんど区別がつきません。データセンターのプロキシは、速度が目立つことが重要で、保護が弱い場合に適しています。
すべての3種類のプロキシはHTTP/HTTPSおよびSOCKS5プロトコルをサポートしているため、コードの観点からは設定は同じです。接続文字列だけが異なります。
cURLにおけるプロキシ: 基本設定
cURL拡張はPHPに標準で搭載されており、サーバー上でHTTPリクエストを実行するための標準的な方法です。プロキシを接続するためには、2つの主要なオプションを使用します: CURLOPT_PROXYとCURLOPT_PROXYTYPEです。
認証なしのHTTPプロキシ
<?php
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://httpbin.org/ip',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_TIMEOUT => 30,
// プロキシのアドレスを指定
CURLOPT_PROXY => '185.199.100.1:8080',
// プロキシの種類: HTTP (デフォルト)
CURLOPT_PROXYTYPE => CURLPROXY_HTTP,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo "HTTPコード: $httpCode\n";
echo $response;
ここでCURLOPT_PROXYはhost:port形式の文字列を受け取ります。cURLはHTTPプロキシを介してHTTPSトラフィックを自動的にCONNECTメソッド — トンネリングを使用するため、リクエストの内容は暗号化されたままになります。
プロキシを使用するためのcURLの便利なオプション
| オプション | 説明 |
|---|---|
CURLOPT_PROXY |
プロキシサーバーのアドレス (host:port) |
CURLOPT_PROXYTYPE |
タイプ: CURLPROXY_HTTP, CURLPROXY_SOCKS4, CURLPROXY_SOCKS5 |
CURLOPT_PROXYUSERPWD |
ユーザー名とパスワードの形式: user:password |
CURLOPT_HTTPPROXYTUNNEL |
HTTP CONNECTを介したトンネリングを有効にする |
CURLOPT_SSL_VERIFYPEER |
SSL証明書の検証 (false — 無効にする) |
CURLOPT_TIMEOUT |
リクエストのタイムアウト(秒) |
CURLOPT_CONNECTTIMEOUT |
プロキシへの接続タイムアウト |
cURLにおける認証とSOCKS5
ほとんどの商用プロキシは、ユーザー名とパスワードによる認証を必要とします。また、SOCKS5は完全な匿名性が必要な場合に推奨されるプロトコルです。なぜなら、プロキシを使用していることを示すX-Forwarded-Forのようなヘッダーを追加しないからです。
ユーザー名とパスワードを使用したHTTPプロキシ
<?php
$proxyHost = '185.199.100.1';
$proxyPort = '8080';
$proxyUser = 'your_login';
$proxyPass = 'your_password';
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://httpbin.org/ip',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_CONNECTTIMEOUT => 10,
// 認証付きプロキシ
CURLOPT_PROXY => "$proxyHost:$proxyPort",
CURLOPT_PROXYTYPE => CURLPROXY_HTTP,
CURLOPT_PROXYUSERPWD => "$proxyUser:$proxyPass",
// HTTPS用のトンネリング
CURLOPT_HTTPPROXYTUNNEL => true,
// マスキング用のブラウザヘッダー
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
CURLOPT_HTTPHEADER => [
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language: ru-RU,ru;q=0.9,en;q=0.8',
],
]);
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo 'cURLエラー: ' . curl_error($ch);
} else {
echo $response;
}
curl_close($ch);
cURLにおけるSOCKS5プロキシ
<?php
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://httpbin.org/ip',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_PROXY => '185.199.100.1:1080',
// DNS解決をプロキシ経由で行うSOCKS5(推奨!)
CURLOPT_PROXYTYPE => CURLPROXY_SOCKS5_HOSTNAME,
// 認証(必要な場合)
CURLOPT_PROXYUSERPWD => 'login:password',
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
💡 重要: SOCKS5 vs SOCKS5_HOSTNAME
CURLPROXY_SOCKS5_HOSTNAMEをCURLPROXY_SOCKS5の代わりに使用してください。違いは、SOCKS5_HOSTNAMEではDNSリクエストもプロキシを通過するため、DNSリークを防ぎ、匿名性が向上します。通常のSOCKS5ではDNSがローカルで解決されるため、実際のIPが漏れる可能性があります。
cURLにおけるプロキシのローテーション
1つのプロキシは、大量のリクエストを行うとすぐにブロックされます。正しい戦略は、プロキシのプールを持ち、それらを交互に使用することです。以下はシンプルで機能的な実装です:
<?php
class ProxyRotator
{
private array $proxies;
private int $currentIndex = 0;
public function __construct(array $proxies)
{
$this->proxies = $proxies;
shuffle($this->proxies); // ランダムな順序にシャッフル
}
/**
* プールから次のプロキシを取得
*/
public function getNext(): string
{
$proxy = $this->proxies[$this->currentIndex];
$this->currentIndex = ($this->currentIndex + 1) % count($this->proxies);
return $proxy;
}
/**
* ランダムなプロキシを取得
*/
public function getRandom(): string
{
return $this->proxies[array_rand($this->proxies)];
}
}
// login:password@host:port形式のプロキシリスト
$proxyList = [
'user1:[email protected]:8080',
'user2:[email protected]:8080',
'user3:[email protected]:8080',
'user4:[email protected]:8080',
];
$rotator = new ProxyRotator($proxyList);
/**
* 自動的にプロキシを選択してリクエストを行う関数
*/
function fetchWithProxy(string $url, ProxyRotator $rotator): ?string
{
$proxyStr = $rotator->getNext();
// プロキシの文字列を解析
preg_match('/^(.+):(.+)@(.+):(\d+)$/', $proxyStr, $m);
[, $user, $pass, $host, $port] = $m;
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_CONNECTTIMEOUT => 8,
CURLOPT_PROXY => "$host:$port",
CURLOPT_PROXYTYPE => CURLPROXY_HTTP,
CURLOPT_PROXYUSERPWD => "$user:$pass",
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
CURLOPT_SSL_VERIFYPEER => false,
]);
$response = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
error_log("プロキシ $host:$port は利用できません: $error");
return null;
}
return $response;
}
// 例: プロキシをローテーションしながら10ページをパース
$urls = [
'https://example.com/page/1',
'https://example.com/page/2',
'https://example.com/page/3',
// ...
];
foreach ($urls as $url) {
$html = fetchWithProxy($url, $rotator);
if ($html) {
echo "取得: " . strlen($html) . " バイト\n";
}
usleep(500000); // リクエスト間の0.5秒の間隔
}
usleep(500000)に注意してください — リクエスト間の間隔は非常に重要です。プロキシをローテーションしても、あまりにも頻繁なリクエストは行動パターンによってブロックされる可能性があります。推奨される間隔は、サイトに応じて500ミリ秒から2秒です。
Guzzle HTTP Clientにおけるプロキシ: 基本設定
Guzzleは、HTTPリクエストのための強力なPHPライブラリであり、ほとんどの現代のPHPフレームワーク(Laravel、Symfony)で使用されています。これは、生のcURLに比べてより便利で読みやすいAPIを提供し、非同期リクエスト、ミドルウェア、エラー処理を簡単に行えます。
Composerを使用したインストール
composer require guzzlehttp/guzzle
認証なしのHTTPプロキシ
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
$client = new Client([
// 基本URL(オプション)
'base_uri' => 'https://httpbin.org',
// すべてのリクエストのデフォルト設定
'timeout' => 30,
'connect_timeout' => 10,
// クライアントのすべてのリクエストに対するプロキシ
'proxy' => 'http://185.199.100.1:8080',
]);
$response = $client->get('/ip');
echo $response->getStatusCode() . "\n"; // 200
echo $response->getBody() . "\n"; // {"origin": "185.199.100.1"}
Guzzleでは、プロキシはURL形式のproxyオプションを介して指定されます。これはcURLよりも直感的です。プロキシはクライアントレベル(すべてのリクエスト用)でも、各リクエストごとに個別に指定することもできます。
認証付きHTTPプロキシ
<?php
use GuzzleHttp\Client;
$login = 'your_login';
$password = 'your_password';
$host = '185.199.100.1';
$port = '8080';
$client = new Client([
'timeout' => 30,
]);
// 認証付きプロキシはURL形式で渡されます
$response = $client->get('https://httpbin.org/ip', [
'proxy' => "http://$login:$password@$host:$port",
'headers' => [
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9',
],
]);
echo $response->getBody();
GuzzleにおけるプロキシURLの形式: scheme://user:password@host:portです。HTTPプロキシにはhttp://を使用し、SOCKS5にはsocks5://を使用します。
Guzzleの高度な使用法: タイムアウト、ヘッダー、SOCKS5
より複雑なシナリオを考慮しましょう: HTTPとHTTPSのための異なるプロキシ、SOCKS5、SSL検証の無効化、ブラウザのエミュレーション用のヘッダーの設定。
HTTPとHTTPSのための異なるプロキシ
<?php
use GuzzleHttp\Client;
$client = new Client([
'timeout' => 30,
'proxy' => [
// HTTPリクエスト用のプロキシ
'http' => 'http://login:[email protected]:8080',
// HTTPSリクエスト用のプロキシ
'https' => 'http://login:[email protected]:8080',
// 除外 — これらのホストはプロキシなしでアクセス
'no' => ['localhost', '127.0.0.1', '.internal.corp'],
],
]);
GuzzleにおけるSOCKS5
<?php
use GuzzleHttp\Client;
// GuzzleでSOCKS5を使用するには追加のパッケージが必要
// composer require clue/socks-react (またはcurlハンドラーを使用)
$client = new Client([
'timeout' => 30,
'proxy' => 'socks5://login:[email protected]:1080',
'curl' => [
CURLOPT_PROXYTYPE => CURLPROXY_SOCKS5_HOSTNAME,
],
]);
$response = $client->get('https://httpbin.org/ip');
echo $response->getBody();
ブラウザヘッダーを使用した完全な構成
<?php
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
$client = new Client([
'timeout' => 30,
'connect_timeout' => 10,
'verify' => false, // SSL検証を無効にする(デバッグ用)
'allow_redirects' => [
'max' => 5,
'strict' => false,
'referer' => true,
'protocols' => ['http', 'https'],
],
'headers' => [
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language' => 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7',
'Accept-Encoding' => 'gzip, deflate, br',
'Cache-Control' => 'no-cache',
'Connection' => 'keep-alive',
],
]);
$response = $client->get('https://example.com/catalog', [
'proxy' => 'http://login:[email protected]:8080',
]);
$statusCode = $response->getStatusCode();
$body = (string) $response->getBody();
echo "ステータス: $statusCode, サイズ: " . strlen($body) . " バイト\n";
⚠️ verify => falseについて
SSL検証を無効にする('verify' => false)のは、デバッグや内部サービスでのみ許可されます。プロダクションコードでは、常にSSL検証を有効にしておく必要があります。そうしないと、マンインザミドル攻撃に対して脆弱になります。
Guzzleにおけるプロキシのローテーション
Guzzleでは、ミドルウェアを介してローテーションを簡単に実装できます — 各リクエストをキャッチしてプロキシを追加する中間層です。これは、各呼び出しにプロキシを手動で渡すよりもエレガントです。
<?php
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use Psr\Http\Message\RequestInterface;
/**
* プロキシの自動ローテーション用ミドルウェア
*/
function proxyRotationMiddleware(array $proxies): callable
{
$index = 0;
$total = count($proxies);
return Middleware::mapRequest(
function (RequestInterface $request) use ($proxies, &$index, $total) {
$proxy = $proxies[$index % $total];
$index++;
// リクエストの属性にプロキシを追加
// (ハンドラーにオプションを介して渡す)
return $request->withHeader('X-Selected-Proxy', $proxy);
}
);
}
// プロキシのリスト
$proxies = [
'http://user1:[email protected]:8080',
'http://user2:[email protected]:8080',
'http://user3:[email protected]:8080',
];
// Guzzleのラッパークラスのシンプルなバージョン
class GuzzleWithRotation
{
private Client $client;
private array $proxies;
private int $index = 0;
public function __construct(array $proxies, array $clientConfig = [])
{
$this->proxies = $proxies;
$this->client = new Client($clientConfig);
}
public function get(string $url, array $options = []): \GuzzleHttp\Psr7\Response
{
$options['proxy'] = $this->proxies[$this->index % count($this->proxies)];
$this->index++;
return $this->client->get($url, $options);
}
public function post(string $url, array $options = []): \GuzzleHttp\Psr7\Response
{
$options['proxy'] = $this->proxies[$this->index % count($this->proxies)];
$this->index++;
return $this->client->post($url, $options);
}
}
// 使用例
$guzzle = new GuzzleWithRotation($proxies, [
'timeout' => 30,
'headers' => [
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
],
]);
$urls = [
'https://example.com/product/1',
'https://example.com/product/2',
'https://example.com/product/3',
];
foreach ($urls as $url) {
try {
$response = $guzzle->get($url);
echo "OK [{$response->getStatusCode()}]: $url\n";
sleep(1);
} catch (\Exception $e) {
echo "エラー: " . $e->getMessage() . "\n";
}
}
エラー処理とデバッグ
プロキシを使用する際、エラーは避けられません: プロキシが利用できない、応答が遅い、またはターゲットサイトがエラーを返すことがあります。これらの状況を適切に処理することが重要です。
cURLにおけるエラー処理
<?php
function fetchWithErrorHandling(string $url, string $proxy): array
{
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_CONNECTTIMEOUT => 8,
CURLOPT_PROXY => $proxy,
CURLOPT_PROXYTYPE => CURLPROXY_HTTP,
]);
$body = curl_exec($ch);
$errno = curl_errno($ch);
$error = curl_error($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$totalTime = curl_getinfo($ch, CURLINFO_TOTAL_TIME);
curl_close($ch);
// プロキシ用のcURLエラーコード
$proxyErrors = [
CURLE_COULDNT_CONNECT => 'プロキシに接続できませんでした',
CURLE_OPERATION_TIMEDOUT => 'プロキシへの接続タイムアウト',
CURLE_RECV_ERROR => 'データ受信エラー',
CURLE_SSL_CONNECT_ERROR => 'プロキシ経由のSSLエラー',
];
if ($errno) {
$message = $proxyErrors[$errno] ?? "cURLエラー #$errno: $error";
return ['success' => false, 'error' => $message, 'code' => $errno];
}
if ($httpCode >= 400) {
return ['success' => false, 'error' => "HTTP $httpCode", 'code' => $httpCode];
}
return [
'success' => true,
'body' => $body,
'code' => $httpCode,
'time' => round($totalTime, 3),
];
}
// リトライを伴う使用例
function fetchWithRetry(string $url, array $proxies, int $maxRetries = 3): ?string
{
foreach ($proxies as $proxy) {
for ($attempt = 1; $attempt <= $maxRetries; $attempt++) {
$result = fetchWithErrorHandling($url, $proxy);
if ($result['success']) {
echo "$proxyを介して成功しました(試行 $attempt, {$result['time']}秒)\n";
return $result['body'];
}
echo "$proxyを介してエラー: {$result['error']}\n";
if ($attempt < $maxRetries) {
sleep(2); // リトライ前の間隔
}
}
}
return null; // すべてのプロキシが機能しなかった
}
Guzzleにおけるエラー処理
<?php
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Exception\ServerException;
use GuzzleHttp\Exception\ClientException;
$client = new Client(['timeout' => 30]);
$proxies = [
'http://user1:[email protected]:8080',
'http://user2:[email protected]:8080',
];
function fetchGuzzleWithFallback(Client $client, string $url, array $proxies): ?string
{
foreach ($proxies as $proxy) {
try {
$response = $client->get($url, [
'proxy' => $proxy,
'timeout' => 20,
]);
return (string) $response->getBody();
} catch (ConnectException $e) {
// プロキシが利用できないか、接続タイムアウト
echo "$proxyは利用できません: " . $e->getMessage() . "\n";
} catch (ClientException $e) {
// HTTP 4xx — クライアントエラー (403, 404, 429)
$code = $e->getResponse()->getStatusCode();
echo "$urlに対するHTTP $code ($proxy)\n";
if ($code === 429) {
echo "レート制限 — 5秒の間隔\n";
sleep(5);
}
} catch (ServerException $e) {
// HTTP 5xx — サーバーエラー
echo "サーバーエラー: " . $e->getResponse()->getStatusCode() . "\n";
} catch (RequestException $e) {
// その他のリクエストエラー
echo "リクエストエラー: " . $e->getMessage() . "\n";
}
}
return null;
}
cURLとGuzzle: どちらを選ぶべきか
両方のツールはプロキシとよく機能しますが、異なる強みがあります。以下は主要な基準に基づく比較です:
| 基準 | cURL | Guzzle |
|---|---|---|
| インストール | ✅ PHPに組み込まれている | ⚠️ Composerが必要 |
| コードの可読性 | ⚠️ オプションが多く、冗長 | ✅ クリーンで便利なAPI |
| パフォーマンス | ✅ わずかに速い(ラッパーなし) | ✅ 比較可能、非同期あり |
| 非同期リクエスト | ⚠️ curl_multi (難しい) | ✅ 組み込みのサポート |
| ミドルウェア / フック | ❌ なし | ✅ HandlerStack、ミドルウェア |
| SOCKS5サポート | ✅ ネイティブ | ✅ curlハンドラー経由 |
| エラー処理 | ⚠️ エラーコードを手動で | ✅ 型付きの例外 |
| Laravel/Symfonyへの統合 | ⚠️ 手動で | ✅ ネイティブサポート |
| 適している用途 | 単純なスクリプト、依存関係なし | フレームワーク上のプロジェクト、複雑なロジック |
推奨: 簡単なスクリプトを書く場合やComposerがないホスティングで作業している場合は、cURLを使用してください。Laravel、Symfony、またはその他の現代的なPHPアプリケーションのプロジェクトには、Guzzleがはるかに便利で、スケーラビリティのためのより多くの機能を提供します。
🚀 起動前のクイックチェックリスト
- ✅ プロキシが動作していることを確認:
curl -x http://login:pass@host:port https://httpbin.org/ip - ✅ タイムアウトを設定:
timeoutとconnect_timeout - ✅ 現実的なUser-Agentを追加
- ✅ リクエスト間に間隔を設ける(最低500ミリ秒)
- ✅ エラー処理と他のプロキシへのフォールバックを考慮
- ✅ SOCKS5にはCURLPROXY_SOCKS5_HOSTNAMEを使用(SOCKS5ではない)
- ✅ プロダクションではSSLの検証を無効にしない
結論
PHPでのプロキシ設定は、正しいオプションと形式を知っていれば難しくありません。基本的なタスクには、CURLOPT_PROXYとCURLOPT_PROXYUSERPWDを使用したcURLで十分です。フレームワーク上のプロジェクトには、Guzzleがより便利なAPI、型付きの例外、プロキシのローテーション用のミドルウェアを提供します。
信頼性のある動作のための重要な原則: DNS解決をプロキシ経由で行うSOCKS5を使用する(CURLPROXY_SOCKS5_HOSTNAME)、常にタイムアウトを設定し、リクエスト間に間隔を設け、スケールの大きなタスクのためにプロキシのローテーションを実装します。エラー処理と他のプロキシへのフォールバックは、すべてのプロダクションコードの必須要素です。
これで、PHPにおけるプロキシの設定と使用方法についての理解が深まったことを願っています。プロキシを適切に使用して、データ収集や自動化のタスクを効率的に行ってください。
```