ヤマト運輸の配送状況を取得するPHPコードの実装方法



## はじめに

ヤマト運輸には公式のAPIがありませんが、送り状番号を入力することで配送状況を取得する仕組みはWeb上に存在します。本記事では、送り状番号を配列に格納し、リクエストを送信することで複数の荷物の配送状況を取得するPHPコードを紹介します。

## 実装の概要

本記事で紹介する実装では、以下の流れで配送状況を取得します。

1. 送り状番号を配列として用意
2. 送り状番号を10件ずつ分割してリクエストを送信
3. 取得したHTMLを解析し、配送状況を抽出
4. 配送状況のデータを整形して出力

## 環境

- PHP 7.4以上
- GuzzleHttp（HTTPクライアントライブラリ）
- DOMDocument（HTML解析用）

## コードの実装

### 1. 送り状番号の設定

まず、配送状況を取得したい送り状番号を配列に格納します。

```php
$trackingNumbers = [
    'ここに12桁の送り状番号',
    'ここに12桁の送り状番号（2）',
    // 必要に応じて追加
];
```

### 2. 配送状況取得処理

次に、ヤマト運輸のサイトへリクエストを送り、配送状況を取得する処理を実装します。

```php
private function fetchYamatoDeliveryStatus(array $trackingNumbers): array
{
    $client = $this->di->get('httpClient');
    $allUpdateData = [];

    foreach (array_chunk($trackingNumbers, 10) as $batch) {
        $formParams = $this->prepareFormParams($batch);

        try {
            $response = $client->request('POST', 'https://toi.kuronekoyamato.co.jp/cgi-bin/tneko', [
                'form_params' => $formParams,
                'headers' => ['Content-Type' => 'application/x-www-form-urlencoded']
            ]);

            $html = (string) $response->getBody();
            $parsedData = $this->yamatoParseSummary($html);

            if ($parsedData) {
                $allUpdateData = array_merge($allUpdateData, $parsedData);
            }
        } catch (\Exception $e) {
            error_log("配送状況の取得中にエラーが発生しました: " . $e->getMessage());
        }
    }
    return $allUpdateData;
}

private function prepareFormParams(array $batch): array
{
    $formParams = [];
    foreach ($batch as $index => $trackingNumber) {
        $formParams[sprintf("number%02d", $index + 1)] = $trackingNumber;
    }
    return $formParams;
}
```

### 3. HTML解析処理

```php
private function yamatoParseSummary(string $html): array
{
    $dom = new DOMDocument();
    libxml_use_internal_errors(true);
    $dom->loadHTML($html);
    libxml_clear_errors();
    $xpath = new DOMXPath($dom);

    $statusRows = $xpath->query("//div[contains(@class, 'tracking-box-area')]");
    $updateData = [];

    foreach ($statusRows as $row) {
        $trackingNumber = $this->getTrackingNumber($xpath, $row);
        $lastUpdated = $this->getLastUpdated($xpath, $row);
        $status = $this->getDeliveryStatus($xpath, $row);

        if (!empty($trackingNumber)) {
            $updateData[] = [
                'tracking_number' => $trackingNumber,
                'status' => $status,
                'last_updated' => $lastUpdated,
            ];
        }
    }
    return $updateData;
}

private function getTrackingNumber(DOMXPath $xpath, DOMNode $row): string
{
    $node = $xpath->query(".//div[contains(@class, 'data number')]/input", $row);
    return $node->length > 0 ? str_replace('-', '', trim($node->item(0)->getAttribute("value"))) : '';
}

private function getLastUpdated(DOMXPath $xpath, DOMNode $row): string
{
    $node = $xpath->query(".//div[contains(@class, 'data date pc-only')]");
    if ($node->length > 0) {
        $currentYear = date('Y');
        return $currentYear . '-' . str_replace('/', '-', trim($node->item(0)->textContent));
    }
    return '';
}

private function getDeliveryStatus(DOMXPath $xpath, DOMNode $row): string
{
    $node = $xpath->query(".//div[contains(@class, 'data state')]/a", $row);
    return $node->length > 0 ? preg_replace('/^\s*▶\s*\d{2}\/\d{2}\s*/u', '', trim($node->item(0)->textContent)) : '';
}
```

## 実行結果のイメージ

このコードを実行すると、以下のようなデータが取得できます。

```json
[
    {
        "tracking_number": "123456789012",
        "status": "配達完了",
        "last_updated": "2024-03-10"
    },
    {
        "tracking_number": "987654321098",
        "status": "輸送中",
        "last_updated": "2024-03-09"
    }
]
```

## まとめ

本記事では、ヤマト運輸の配送状況を取得するPHPコードを紹介しました。

- GuzzleHttp を利用して HTTP リクエストを送信
- 配送状況の取得を 10 件ずつのバッチ処理で実行
- DOMDocument と XPath を使って HTML を解析

この方法を活用すれば、より効率的に配送状況を取得できます。是非参考にしてください！