自動化スクレイピング

【初心者向け】PHPを使ってスクレイピングをする方法をわかりやすく解説

PHPでスクレイピングを始めたい初心者向けに、cURL/GuzzleでのHTML取得からDOMDocument・XPath、Symfony DomCrawlerでの抽出までを手順付きで解説。よくある失敗、エラー処理、規約・robots.txt確認など安全運用の要点も整理します。

Ibuki Yamamoto
Ibuki Yamamoto
2026年1月15日 18分で読めます

【初心者向け】PHPを使ってスクレイピングをする方法をわかりやすく解説

PHPでスクレイピングを始めるなら、「HTTPでHTMLを取得して、DOMで必要な要素を抜き出す」が基本です。本記事では、cURL(またはGuzzle)で取得し、DOMDocument/XPathやSymfony DomCrawlerで抽出する手順を、失敗しやすいポイントも含めて整理します。

この記事でわかること
  • PHPでHTMLを取得し、要素を抽出する基本手順
  • DOMDocument・XPathとDomCrawlerの使い分け
  • 失敗を減らすエラー処理とマナー(負荷・規約)

スクレイピング概要

スクレイピングは、Webページ(主にHTML)から必要な情報を取り出して加工・保存する一連の処理です。初心者が最初に押さえるべき構成は次の2段階です。

  1. HTTPでページを取得する(GET)
  2. HTMLを解析して、必要な要素を抽出する(DOM/CSS/XPath)

まずは静的ページから始めるのがおすすめです。JavaScriptで描画されるページ(動的ページ)は、取得したHTMLに目的の要素が含まれないことが多く、難易度が上がります。

事前に確認すること

規約とrobots.txt

スクレイピングを始める前に、対象サイトの利用規約・ガイドライン、そしてrobots.txtを確認してください。robots.txtはクローラ向けのアクセス方針を示す仕組みとして標準化されています(Robots Exclusion ProtocolはRFC 9309として文書化)。

注意: robots.txtの許可・禁止は「技術的に強制するもの」ではありませんが、運用上の重要な合意事項です。禁止されているパスの収集や高頻度アクセスは、ブロックや法的トラブルにつながる可能性があります。

取得方式の見極め

  • 静的HTML: cURL/Guzzleで取得→DOM解析でOK
  • 動的描画: APIが裏にある場合はAPIを叩く(規約の範囲で)/ブラウザ自動化が必要になることも

全体フロー

実装の流れを最短で掴むために、最小構成を先に提示します。

  1. URLにGETしてHTML文字列を得る
  2. 文字化け対策(必要なら)
  3. DOMとしてパースする
  4. XPath/CSSセレクタで要素を特定して抽出
  5. 保存(CSV/DB/JSON)

HTMLを取得する

cURLで取得する

PHP標準のcURL拡張で取得する方法です。User-Agentの設定、リダイレクト追従、タイムアウト、文字コードなどを最低限入れておくと失敗が減ります。PHPのcURL利用例として、CURLOPT_RETURNTRANSFERCURLOPT_FOLLOWLOCATIONCURLOPT_USERAGENTなどが一般的に使われます。

<?php
$url = 'https://example.com/';

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_CONNECTTIMEOUT => 10,
    CURLOPT_TIMEOUT => 20,
    CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible; MyScraper/1.0; +https://example.com/bot)',
]);

$html = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);

if ($html === false) {
    throw new RuntimeException('cURL error: ' . $error);
}
if ($httpCode < 200 || $httpCode >= 300) {
    throw new RuntimeException('HTTP error: ' . $httpCode);
}

echo $html;

ポイント: 一部サイトはUser-Agent未設定だと403になることがあります。最低限のUA設定と、タイムアウト設定は入れておきたいところです。

Guzzleで取得する

実務では、HTTPクライアントとしてGuzzleを使うと、例外処理・ヘッダ管理・ミドルウェアなどが整理しやすくなります。Guzzleは「PHP HTTP client」として機能を提供し、Composerで導入できます。github.com

composer require guzzlehttp/guzzle
<?php
require __DIR__ . '/vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client([
    'timeout' => 20,
    'connect_timeout' => 10,
    'headers' => [
        'User-Agent' => 'Mozilla/5.0 (compatible; MyScraper/1.0; +https://example.com/bot)',
    ],
]);

$response = $client->request('GET', 'https://example.com/');
$html = (string) $response->getBody();

echo $html;

HTMLを解析する

DOMDocumentの注意

PHPのDOMDocumentでHTMLを読み込むにはDOMDocument::loadHTML()を使います。ただし公式ドキュメントでは、loadHTML()はHTML4パーサであり、モダンHTML(HTML5)のパースルールと差が出る可能性がある点、そして無害化目的で安全に使えない点が明確に警告されています。php.net

注意: 「ブラウザで見えているDOM」と「DOMDocumentが作るDOM」が一致しないケースがあります。要素が取れないときは、(1)取得HTMLが想定と違う (2)動的描画 (3)パース差分 の順で疑ってください。

XPathで抽出する

DOMDocumentとDOMXPathを組み合わせると、追加ライブラリなしで抽出できます。エラー抑制と後処理をするために、libxmlの内部エラー管理も合わせて使うのが定番です。libxmlはエラーを内部に保持でき、後から取り出して処理できます。php.net

<?php
libxml_use_internal_errors(true);

autoload(); // 必要に応じて

$html = '<html><body><h1 class="title">Hello</h1></body></html>';

$dom = new DOMDocument();
$dom->loadHTML($html);

$xpath = new DOMXPath($dom);
$nodes = $xpath->query("//h1[@class='title']");

if ($nodes !== false && $nodes->length > 0) {
    echo trim($nodes->item(0)->textContent);
}

libxml_clear_errors();

DomCrawlerで抽出

SymfonyのDomCrawlerを使うと、CSSセレクタで直感的に抽出できます。公式ドキュメントでも、CrawlerがHTML/XMLをたどり、CSSセレクタ(filter())やXPath(filterXpath())でノードを選択できることが説明されています。symfony.com

composer require symfony/dom-crawler symfony/css-selector
<?php
require __DIR__ . '/vendor/autoload.php';

use Symfony\Component\DomCrawler\Crawler;

$html = '<html><body><h1 class="title">Hello</h1></body></html>';
$crawler = new Crawler($html);

$title = $crawler->filter('h1.title')->text();
echo trim($title);

使い分け: 小規模・依存を増やしたくないならDOMDocument+XPath。抽出が増える・CSSセレクタで書きたいならDomCrawlerが便利です。

実用テンプレ

「取得→抽出」を1ファイルで回せる、学習用の最小テンプレです(静的ページ想定)。

<?php
// 1) 取得
function fetchHtml(string $url): string {
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_TIMEOUT => 20,
        CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible; MyScraper/1.0; +https://example.com/bot)',
    ]);

    $html = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $error = curl_error($ch);
    curl_close($ch);

    if ($html === false) {
        throw new RuntimeException('cURL error: ' . $error);
    }
    if ($httpCode < 200 || $httpCode >= 300) {
        throw new RuntimeException('HTTP error: ' . $httpCode);
    }

    return $html;
}

// 2) 抽出(XPath)
function extractTitles(string $html): array {
    libxml_use_internal_errors(true);

    $dom = new DOMDocument();
    $dom->loadHTML($html);
    $xpath = new DOMXPath($dom);

    $nodes = $xpath->query("//h2");
    $titles = [];

    if ($nodes !== false) {
        foreach ($nodes as $node) {
            $titles[] = trim($node->textContent);
        }
    }

    libxml_clear_errors();
    return $titles;
}

$url = 'https://example.com/';
$html = fetchHtml($url);
$titles = extractTitles($html);

foreach ($titles as $t) {
    echo $t . PHP_EOL;
}

よくある失敗

取得HTMLが空

  • 403/429(アクセス制限): User-Agent、アクセス頻度、IP、Cookie要件を確認
  • リダイレクト先でブロック: CURLOPT_FOLLOWLOCATIONの有無を確認
  • タイムアウト: 接続/全体タイムアウトを調整

要素が取れない

  • ページが動的描画で、HTML内に目的要素が無い
  • DOMDocumentのパース差分でDOM構造が変わる(HTML4パーサ警告に該当)php.net
  • セレクタが弱い(クラス名変更に弱い)

libxmlの警告が多い

壊れたHTMLでは警告が出やすいです。libxmlの内部エラー管理を使い、必要ならエラー内容をログに回してください。php.net

ライブラリ比較

初心者が選びやすいように、取得と抽出を分けて比較します。

用途 選択肢 強み 弱み
HTTP取得 cURL 標準機能で完結しやすい 実装が手続き的になりやすい
HTTP取得 Guzzle HTTP周りの整理がしやすい(PSR対応など) Composer導入が前提
HTML抽出 DOMDocument+XPath 軽量・依存が少ない HTML5とのパース差分が出ることがある
HTML抽出 Symfony DomCrawler CSSセレクタで書けて保守しやすい ライブラリ導入が必要

公式仕様の要点

DOMDocument::loadHTMLはHTML4パーサを使い、HTML5のパースルールとは異なるため、DOM構造が異なる可能性がある(公式ドキュメントの警告)。php.net

「取れない=コードが悪い」と決めつけず、パーサ仕様や取得できているHTML自体を検証するのが近道です。

安全に運用する

アクセス頻度を抑える

  • 1リクエストごとに待機(例: 1〜3秒)
  • リトライは上限回数を決める
  • 429/503が出たら中断・間隔を延ばす

取得結果をキャッシュ

同じページを何度も取得しないだけで、ブロックや負荷のリスクが下がります。学習段階でも、取得HTMLをローカルに保存して解析を繰り返すと効率的です。

収集を自動化しませんか?

スクレイピングの設計から運用(ブロック対策・監視・安定稼働)まで一貫して相談できます。要件に合わせて安全な収集フローをご提案します。

お問い合わせスクレイピングに関するご相談・お見積もりはお気軽にどうぞ
相談する

まとめ

  • PHPスクレイピングは「取得(cURL/Guzzle)+抽出(XPath/DomCrawler)」が基本
  • DOMDocumentはHTML5と差分が出ることがあるため、取れないときは仕様と取得HTMLを確認
  • 規約・robots.txt確認、低頻度アクセス、キャッシュで安全に運用する

この記事を書いた人

Ibuki Yamamoto
Ibuki Yamamoto

Webスクレイピングエンジニア。10年以上の実務経験を持ち、大規模なデータ収集プロジェクトを数多く手がける。PythonとJavaScriptを得意とし、技術ブログでは実践的なスクレイピング手法を発信している。

データ収集のプロに
お任せください

年間1億件以上のデータ収集実績を持つプロフェッショナルチームが、大規模スクレイピング・アンチボット対策など、あらゆる課題を解決します。

1億+
年間データ収集件数
24/7
安定稼働
高品質
データ精度