Symfony dom-crawlerのインストール
インストール
SymfonyのDom-crawlerをインストールします。
ターミナルで以下のコマンドを実行します。
composer require symfony/dom-crawler
インストールが完了すると、composer.jsonとcomposer.lockファイルが更新されます。
composer.json
"require": {
(省略)
"olssonm/l5-very-basic-auth": "^6.4",
"symfony/dom-crawler": "^5.3"
},
composer.lock
{
"name": "symfony/dom-crawler",
"version": "v5.3.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/dom-crawler.git",
"reference": "c7eef3a60ccfdd8eafe07f81652e769ac9c7146c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/c7eef3a60ccfdd8eafe07f81652e769ac9c7146c",
"reference": "c7eef3a60ccfdd8eafe07f81652e769ac9c7146c",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php80": "^1.16"
},
"conflict": {
"masterminds/html5": "<2.6"
},
"require-dev": {
"masterminds/html5": "^2.6",
"symfony/css-selector": "^4.4|^5.0"
},
"suggest": {
"symfony/css-selector": ""
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\DomCrawler\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Eases DOM navigation for HTML and XML documents",
"homepage": "https://symfony.com",
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-08-29T19:32:13+00:00"
},
dom-crawlerの使い方
ここでは例としてページのHTMLコードを直接渡して欲しいデータを取得します。
コードはコントローラやヘルパなどに記載します。
use Symfony\Component\DomCrawler\Crawler;
$html = <<<'HTML'
<!DOCTYPE html>
<html>
<body>
<div id="first-wrapper" >
<p class="greeting">Hello World!</p>
</div>
<div id="second-wrapper">
<p class="program">Laravel</p>
</div>
<p>Crawler!</p>
</body>
</html>
HTML;
$crawler = new Crawler($html);
dump($crawler);
上記処理は、new Crawler($html)
で、HTML要素をクローリングしてオブジェクトとして扱えるようにしています。
dump($cralwer)でクローリングした中身を表示します。
Symfony\Component\DomCrawler\Crawler {#335 ▼
#uri: null
-defaultNamespacePrefix: "default"
-namespaces: []
-cachedNamespaces: ArrayObject {#325 ▶}
-baseHref: null
-document: DOMDocument {#336 ▶}
-nodes: array:1 [▶]
-isHtml: true
-html5Parser: null
}
便利なメソッド
new Crawlerでクローリングした内容はメソッドを使って欲しい情報を絞り込むことができます。
基本的にはfilterメソッドなどで絞り込みをし、textメソッドやattrメソッドで値を抽出する形になります。
タグの絞り込み(filter系など)
メソッド | 内容 |
---|---|
filter(‘タグ名’) | 指定したタグ名のデータを全て取得 |
filter(‘タグ名1 > タグ名2’) | タグ名1の直下にあるタグ名2のデータを全て取得 |
filter(‘#id名’) | 指定したid名のデータを取得 |
filter(‘.クラス名’) | 指定したクラス名のデータを全て取得 |
filter(‘タグ名.クラス名’) | 指定したクラス名を持つ指定したタグのデータを全て取得 |
filterxPath(‘xPath’) | xPathで要素を指定 |
クラス名で指定する場合は、CSSのセレクタと同じ指定方法が使えます。
filter後の絞り込み
fiterの後に複数のタグがある場合は、続けて絞り込みをするメソッドが用意されています。
メソッド | 内容 |
---|---|
first() | 1つ目のタグのデータ |
eq(数値) | 指定した数値のデータ。1つ目のタグならeq(0)。 |
last() | 最後のタグのデータ |
siblings() | 同じ階層にあるデータ |
children() | 全ての子要素 |
ancestors() | 全ての親要素 |
nextAll() | 同じ階層の以降のタグのデータ |
previousAll() | 同じ階層の以前のタグのデータ |
children('p.common')
のようにさらにタグを絞り込むこともできます。(例は取得したタグの中のクラス名commonを持つpタグを指定)
値を取得する
タグに囲まれた文字列(値)を取得する時は、text()を使います。
メソッド | 内容 |
---|---|
text() | タグの値を取得する。タグが複数ある場合は1つ目のタグの値。 |
attr(‘属性名’) | 指定した属性の値を取得する。attr(‘id名’)なら指定したid名の値を取得。 |
▼テキスト抽出の実例
body直下の1つ目のpタグの値を取得し、dumpで画面上に表示します。
$crawler = new Crawler($html);
$message = $crawler->filter('body > p')->eq(1)->text();
dump($message);
指定した要素か確認する
matchesメソッド(※複数形)を使うと、指定した値と一致していればtrue、不一致ならfalseを返します。
メソッド | 内容 |
---|---|
matches(‘指定’) | 指定した値と一致していればtrue、不一致ならfalseを返す。 |
指定方法はfilterと同じです。前方にfilterなどで絞り込んだ要素に対して使います。
$crawler->filter('body > div')->first()->matches('div#first-wrapper');
全ての値を取得する(eachメソッド)
text()を使うと最初のデータの値しか取得できません。複数のタグがある場合はeachメソッドを使います。
each( function( $変数, $インデックス番号用の変数 ){ 処理 } )
例:複数のデータを取得して配列に格納する
use Symfony\Component\DomCrawler\Crawler;
$html = <<<'HTML'
<!DOCTYPE html>
<html>
<body>
<div id="first-wrapper" >
<p class="greeting">Hello World!</p>
</div>
<div id="second-wrapper">
<p class="program">Laravel</p>
</div>
<p>Crawler!</p>
</body>
</html>
HTML;
$crawler = new Crawler($html);
$arr = $crawler->filter('div > p')->each(function($el){
return ($el->text());
});
dump($arr);
▼出力
array:2 [▼
0 => "Hello World!"
1 => "Laravel"
]
例:複数のデータを連想配列として取得する
連想配列として取得する例です。
$html = <<<'HTML'
<!DOCTYPE html>
<html>
<body>
<div id="first-wrapper" >
<p class="greeting">Hello World!</p>
</div>
<div id="second-wrapper">
<p class="program">Laravel</p>
</div>
<p>Crawler!</p>
</body>
</html>
HTML;
$crawler = new Crawler($html);
$arr = $crawler->filter('div')->each(function($el, $i){
$id = $el->attr('id'). $i;
$text = $el->text();
return [
"id-" . $i => $id,
"text-" . $i => $text,
];
});
dump($arr);
▼出力
array:2 [▼
0 => array:2 [▼
"id-0" => "first-wrapper0"
"text-0" => "Hello World!"
]
1 => array:2 [▼
"id-1" => "second-wrapper1"
"text-1" => "Laravel"
]
]