正規表現で後方参照を使うとスクレイピングがまぁ捗るよって話

プログラミング

こんにちは、つばさ(@tsubasa123)です。

今日はちょっとシステム要素高め、そして短めでお送りします。タイトル通り、正規表現の後方参照について。興味のない方はまたの機会にお会いしましょう。正規表現ビギナーな私がマニュアルみて見つけた時のことを嬉々として綴りますのでお付き合いください。

事前知識として

正規表現にも色々あるようですが、今回はPHPという言語のpreg_match()関数とかpreg_match_all()関数とかに関するお話です。あんまり詳しくは突っ込みません(突っ込めません)。

正規表現では()(括弧)を利用して、パターン内で一致した部分の文字列を参照することができます。

<?php
preg_match(/ab(.*?)hij/is, 'abcdefghijklmn', $match);
var_dump($match);
array(2) {
[0]=>
string(10) "abcdefghij"
[1]=>
string(5) "cdefg"
}

こんな感じ。マッチした全体だけでなく、括弧で囲んだ範囲だけを切り取ることも可能です。これはいいですね、よく使うやつです。

で、後方参照を使うと

括弧で囲まれた範囲をパターンの中でも使うことができるようになります。後方参照を使うには「\1」のようにバックスラッシュを数字の前に配置します。指定した数字と一致する順番の括弧内の文字列がパターンに適応されます。

実例を見たほうがわかりやすいですね、きっと。

<?php
$s = '<h1>aaaaa</h1>';
$s .= '<h2>bbbbb</h2>';
$s .= '<h3>ccccc</h3>';
preg_match_all('/<h([1-6]{1})[^>]*>(.*?)<\/h\1>/is', $s, $match);
var_dump($match);
array(3) {
[0]=>
array(3) {
[0]=>
string(14) "<h1>aaaaa</h1>"
[1]=>
string(14) "<h2>bbbbb</h2>"
[2]=>
string(14) "<h3>ccccc</h3>"
}
[1]=>
array(3) {
[0]=>
string(1) "1"
[1]=>
string(1) "2"
[2]=>
string(1) "3"
}
[2]=>
array(3) {
[0]=>
string(5) "aaaaa"
[1]=>
string(5) "bbbbb"
[2]=>
string(5) "ccccc"
}
}

こんな感じ。ビギナーな私にはこのくらいが精一杯なんですが、<\/h\1>ここがポイントですね。パターンの先頭で<h([1-6]{1})[^>このように、h1~h6までの見出しを定義していますが、これに一致した閉じタグまでの範囲を取得するために後方参照を利用することができます。

取得結果の方は、配列の先頭にマッチした文字列、二番目に後方参照で取得した文字列、三番目以降に括弧でキャプチャした文字列が取得できます。いやー、これは便利。後方参照を知るまではタグごとに正規表現を利用してコンテンツを取得し、最後にマージするみたいなかっこ悪いことしてましたけど、これなら一回で済みますからね。

ちなみに、

PHP: preg_match_all – Manual

PHPのリファレンスの「例2 HTML タグにマッチするものを見付ける(貪欲)」にHTMLのタグの取得方法も書かれています。あっちのほうが汎用性高めなので、合わせてチェックしましょう。

これを駆使すると…

いろんなサイトのいろんな情報を取得して整形したりすることができるようになります。いわゆる「スクレイピング」と呼ばれるやつですね。とあるブログのカスタマイズをお手伝いさせていただいていますが、このような技術を利用してHTMLから必要なデータを取得してコンテンツを作成して提供する予定です。手動だと大変ですからね。

ちなみに、悪用すればあれですね。そう、悪いこともできます。世に蔓延るパクリコンテンツも、原点回帰するとこんなことをしているんじゃないでしょうか。パクリダメゼッタイ。

まぁ、スクレイピング用のライブラリもあったりしますので、わざわざ正規表現を選択するメリットはないかもですが、基本を押さえておくことは重要だったりします。正規表現が使えればこんなこともできるよ、って話です。

さいごに

はじめて後方参照を知った時の喜びを誰かにお届けしたくて記事を書いてみましたが、私自身が正規表現に精通していないので薄っぺらい内容しか書くことができませんでした。勉強不足ですね、面目ない。書籍だけは手元にあるので、またの機会に勉強結果をアウトプットできればいいなと思う次第です。

ではでは、最後までお付き合いいただきありがとうございました。

コメント