目次
サンプル・プログラムの実行例
存在チェックを実施したくないURLを、除外パターンとして正規表現で複数指定することができる。パターンはPHPの正規表現と同様、スラッシュで囲む /.../ こと。2つ以上のパターンを指定したいときは、改行で区切る。たとえば、"/e-soul/webtech/php02/" で始まるURLを除外したければ、
/https\:\/\/www\.pahoo\.org\/e\-soul\/webtech\/php02\//と入力する。
サンプル・プログラム
| check404.php | サンプル・プログラム本体。 |
| pahooInputData.php | データ入力に関わる関数群。 使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。 |
| pahooScraping.php | スクレイピングS処理に関わるクラス pahooScraping。 スクレイピング処理に関わるクラスの使い方は「PHPで作るRSSビューア」を参照。include_path が通ったディレクトリに配置すること。 |
| バージョン | 更新日 | 内容 |
|---|---|---|
| 5.3.0 | 2025/12/28 | PHP8.5対応:curl_closeを使わない |
| 5.2.0 | 2025/05/10 | getHttpResponseCodeSize()-リクエストヘッダ改良 |
| 5.1.0 | 2025/03/09 | getContext() -- Referer生成機能追加 |
| 5.0.0 | 2024/11/15 | 全面改訂:XPath式導入, アクセス回数低減 |
| 4.6.0 | 2023/03/21 | htmlChecker→validateHTMLに変更 |
| バージョン | 更新日 | 内容 |
|---|---|---|
| 2.0.1 | 2025/08/11 | getParam() bug-fix |
| 2.0.0 | 2025/08/11 | pahooLoadEnv() 追加 |
| 1.9.0 | 2025/07/26 | getParam() 引数に$trim追加 |
| 1.8.1 | 2025/03/15 | validRegexPattern() debug |
| 1.8.0 | 2024/11/12 | validRegexPattern() 追加 |
| バージョン | 更新日 | 内容 |
|---|---|---|
| 1.2.1 | 2024/10/31 | __construct() 文字化け対策 |
| 1.2.0 | 2024/09/29 | getValueFistrXPath() 属性値でない指定に対応 |
| 1.1.0 | 2023/10/15 | getValueFistrXPath() 追加 |
| 1.0.1 | 2023/09/29 | __construct() bug-fix |
| 1.0.0 | 2023/09/18 | 初版 |
準備
check404.php
59: // 初期値(START) ============================================================
60: // 表示幅(ピクセル)
61: define('WIDTH', 600);
62:
63: // 偽装ユーザー
64: define('USER_AGENT', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36');
65:
66: // スクレイピング処理に関わるクラス:include_pathが通ったディレクトリに配置
67: require_once('pahooScraping.php');
68:
69: // デフォルトのスクレイピング対象クエリ
70: $text = [
71: "//a/@href",
72: "//img/@src",
73: "//link/@href",
74: "//script/@src",
75: "//meta[@name='og:url']/@content",
76: "//meta[@name='og:image']/@content",
77: "//meta[@name='twitter:image']/@content",
78: "//link[@rel='canonical']/@href",
79: ];
80: define('XPATH_LIST', $text);
81:
82: // デフォルトの除外パターン(チェック対象外URL)リスト
83: define('DEF_EXCLUDE', '');
84:
85: // 初期値(END) ==============================================================
後述するユーザー関数の幾つかで、ブラウザからアクセスが来ているように見せかけるために、USER_AGENT の偽装値を設定しておく。
リンク先を検出するのに、XPath式を利用する。XPath式 およびユーザー定義クラス pahooScraping については「PHPでDOMDocumentを使ってスクレイピング」をご覧いただきたい。
下表に示すタグにあるリンク先をデフォルトでチェックするよう、定数 XPATH_LIST に代入してある。過不足があれば、適宜編集してほしい。
| XPath式 | 意味 |
|---|---|
| //a/@href | aタグのhref属性にあるリンク |
| //img/@src | imgタグのsec属性にあるリンク |
| //link/@href | linkタグのhref属性にあるリンク |
| //script/@src | scriptaタグのsrc属性にあるリンク |
| //meta[@name='og:url']/@content | metaタグのname属性がog:urlのものでcontent属性にあるリンク |
| //meta[@name='og:image']/@content | metaタグのname属性がog:imageのものでcontent属性にあるリンク |
| //meta[@name='twitter:image']/@content | metaタグのname属性がtwitter:imageのものでcontent属性にあるリンク |
| //link[@rel='canonical']/@href | linkタグのrel属性がcanonicalのものでhref属性にあるリンク |
解説:404エラーのチェック
check404.php
418: /**
419: * 指定コンテンツに含まれるリンク先の有無を配列に格納する
420: * @param string $sour コンテンツURL
421: * @param array $items チェック結果を格納する配列
422: * @param string $errmsg エラーメッセージを格納
423: * @param string $queryList チェック対象のXPath式の配列
424: * @param string $exclude チェック除外するURLパターン
425: * (正規表現の配列;省略時はNULL)
426: * @return bool TRUE:処理成功/FALSE:失敗(引数のエラーなど)
427: */
428: function check404($sour, &$items, &$errmsg, $queryList=XPATH_LIST, $excludes=NULL) {
429: $context = getContext($sour);
430: $contents = @file_get_contents($sour, FALSE, $context);
431: if ($contents == FALSE) {
432: $errmsg = $url . ' は存在しない.';
433: return FALSE;
434: }
435:
436: // スクレイピング開始
437: $pcr = new pahooScraping($contents);
438: $index = 0;
439:
440: // チェック対象のXPath式を1つずつ調べていく
441: foreach ($queryList as $query) {
442: $imageNode = $pcr->queryXPath($query);
443: // XPath式に合致するノードを1つずつ調べていく
444: foreach ($imageNode as $node) {
445: // URLチェックを行うフラグを立てる
446: $flagCheck = TRUE;
447: // ノードにあるURLを正規化する
448: $url = normalizeURLs((string)$node->nodeValue, $sour);
449: // それがURLでなければスキップ
450: if ($url == FALSE) {
451: continue;
452: }
453: // そのURLが除外URL配列に含まれていたら
454: // この後の処理をスキップするようフラグを降ろす
455: if ($excludes != NULL) {
456: foreach ($excludes as $exclude) {
457: if (preg_match($exclude, $url)) {
458: $flagCheck = FALSE;
459: break;
460: }
461: }
462: }
463: if ($flagCheck) {
464: // そのURLが存在するかどうか、サイズなどの情報を配列に格納
465: checkLink($url, (int)$node->getLineNo(), $items);
466: $index++;
467: }
468: }
469: }
470: // スクレイピング終了
471: $pcr = NULL;
472:
473: // 行番号の小さい順に並び替える
474: usort($items, function ($a, $b) {
475: return $a['ln'] > $b['ln'] ? (+1) : (-01);
476: });
477: }
調査するコンテンツのURLを引数 $sour に渡し、与えられた XPath式(複数)を使って、そのコンテンツの中に含まれているリンク先URを取りだし、それがが存在するかどうかを、後述するユーザー関数 checkLink を使って調べる。
まず、調査対象の $sour が存在するかどうかを、組み込み関数 file_get_contents を使って検証する。このとき、第三引数に後述するユーザー関数 getContext で生成したストリームコンテキストを渡すことで、ブラウザからアクセスしているように見せかける。
次に、ユーザー定義クラス pahooScraping を使ってスクレイピングを開始する。
for文を使い、引数で渡された XPath式 の連想配列を1つずつ調べていく。XPath式 に合致するパターンがあれば、そのノードを配列 $imageNode に代入する。
for文を使い、ノード配列 $imageNode を1つずつ調べていく。
まず、URLチェックを行うフラグ変数 $flagCheck を立てる。
次に、XPath式を使って得られるリンク先は "http(s)://" ではじまらない相対リンクのこともあるので、後述するユーザー関数 normalizeURLs を使って "http(s)://" ではじまるように正規化してから変数 $url に代入する。
$url が引数として渡された除外URL配列 $excludes に合致したら、これ以降の処理をスキップするよう、フラグ変数 $flackCheck を降ろす。
最後に、フラグ変数 $flagCheck が立っていれば、得られたURLが存在するかどうかを、後述するユーザー関数 checkLink を使ってチェックし、結果を連想配列 $items に格納する。
以上の二重ループを抜けたら、結果を格納している連想配列 $items を、行番号の小さい順に並び替える。
解説:ストリームコンテキスト作成
check404.php
240: /**
241: * 偽装用のcontextを返す
242: * @param string $url 対象URL
243: * @param object コンテクスト
244: */
245: function getContext($url) {
246: // Refererを生成する
247: $parsedUrl = parse_url($url);
248: $referer = $parsedUrl['scheme'] . '://' . $parsedUrl['host'] . '/';
249:
250: //偽装ヘッダ
251: $header = array(
252: 'Content-Type: text/html; charset=UTF-8',
253: 'User-Agent: ' . USER_AGENT,
254: 'Referer: ' . $referer
255: );
256: $ssl = array(
257: 'verify_peer' => FALSE,
258: 'verify_peer_name' => FALSE
259: );
260: $opts = array(
261: 'http' => array(
262: 'method' => 'GET',
263: 'header' => implode("\r\n", $header),
264: 'ssl' => $ssl,
265: 'follow_location' => 1, // リダイレクトを追跡する
266: 'max_redirects' => 10, // 最大リダイレクト回数
267: )
268: );
269:
270: return stream_context_create($opts);
271: }
本プログラムでは、ブラウザがサーバと通信している状態を再現して404エラーが起きるかどうかをチェックするために、これらの情報を組み込み関数 stream_context_creat を使って用意する。用意する情報は、getContext に書かれているとおりだ。
Referer として、対象URLのホスト名を利用する。
これらはアクセス偽装と呼ばれる手法だが、別に悪い意味はないので、念のため。
解説:指定したURLが存在するかどうかを連想配列に格納
check404.php
363: /**
364: * 指定したURLが存在するかどうかを配列に格納する
365: * @param string $url チェックするURL(正規化済)
366: * @param int $ln 解析中の行番号
367: * @param array $items チェック結果を格納する配列
368: */
369: function checkLink($url, $ln, &$items) {
370: $arr = array();
371:
372: // URLが $items に含まれていたら行番号以外をコピーして終了
373: // ネットへの余計なアクセスを減らすため
374: foreach ($items as $item) {
375: if ($item['url'] == $url) {
376: $arr['ln'] = $ln;
377: $arr['url'] = $url;
378: $arr['res'] = $item['res'];
379: $arr['size'] = $item['size'];
380: $items[] = $arr;
381: return;
382: }
383: }
384:
385: // cURL関数を使って存在チェックする
386: if (function_exists('curl_exec')) {
387: list($code, $size) = getHttpResponseCodeSize($url);
388: if (($code != NULL) && ($code != 200)) {
389: $arr['res'] = 'なし';
390: $size = (-1);
391: //サイズ>0 または パス指定
392: } else if (($size > 0) || (preg_match('/\/$/ui', $url) > 0)) {
393: $arr['res'] = 'あり';
394: } else {
395: $arr['res'] = 'ゼロ';
396: $size = 0;
397: }
398:
399: // getContentsSize関数を使って存在チェックする
400: } else {
401: $size = getContentsSize($url);
402: if ($size < 0) {
403: $arr['res'] = 'なし';
404: } else if ($size == 0) {
405: $arr['res'] = 'ゼロ';
406: } else {
407: $arr['res'] = 'あり';
408: }
409: }
410:
411: // 配列に追加する
412: $arr['url'] = $url; // 対象URL
413: $arr['ln'] = $ln; // 対象URLがある行番号
414: $arr['size'] = $size; // コンテンツ・サイズ(バイト)
415: $items[] = $arr;
416: }
存在するかどうかをチェックするのに、3つの場合分けをしている。
- すでに連想配列 $items に登録されていれば、その内容をコピーする(行番号だけ解析中のものにする)。これは余計なネットワークアクセスを減らすための工夫だ。
- PHP処理系にcURL関数が実装されていれば、cURL関数を使って存在チェックする。
- それ以外の場合は、ユーザー関数 getContentsSize を使って存在チェックする。
- url‥‥対象URL
- ln‥‥対象URLがある行番号(表示用)
- size‥‥コンテンツ・サイズ(バイト)
- res‥‥あり/なし/ゼロ(表示用)
解説:HTTPレスポンスコード、サイズを取得
check404.php
291: /**
292: * HTTPレスポンスコード、サイズを取得
293: * @param string $url チェックするURL
294: * @return array(HTTPステータスコード:200 正常/NULL 取得失敗, サイズ)
295: */
296: function getHttpResponseCodeSize($url) {
297: // Refererを生成する
298: $parsedUrl = parse_url($url);
299: $referer = $parsedUrl['scheme'] . '://' . $parsedUrl['host'] . '/';
300:
301: // ヘッダー設定
302: $header = array(
303: 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
304: 'Accept-Language: ja,en-US;q=0.9,en;q=0.8',
305: 'Cache-Control: max-age=0',
306: 'User-Agent: ' . USER_AGENT,
307: 'Referer: ' . $referer,
308: );
309:
310: // cURL関数を使ってコンテンツをオープンする
311: $options = array(
312: CURLOPT_RETURNTRANSFER => TRUE, // ホスト名の検証を無効化
313: CURLOPT_HEADER => TRUE, // HTTPステータスコードを返す
314: CURLOPT_HTTPHEADER => $header, // ヘッダ情報
315: CURLOPT_SSL_VERIFYPEER => FALSE, // SSL証明書の検証を無効化
316: CURLOPT_SSL_VERIFYHOST => FALSE, // ホスト名の検証を無効化
317: CURLOPT_FOLLOWLOCATION => TRUE, // リダイレクト先に自動アクセス
318: CURLOPT_AUTOREFERER => TRUE, // リダイレクト先にReferer設定
319: CURLOPT_MAXREDIRS => 10, // リダイレクトを追跡する最大回数
320: CURLOPT_CONNECTTIMEOUT => 120, // 接続開始までの最大待ち時間
321: CURLOPT_TIMEOUT => 120, // リクエスト終了までの最大時間
322: CURLOPT_ENCODING => '', // ヘッダのエンコーディンング
323: );
324: $ch = curl_init($url);
325: curl_setopt_array($ch, $options);
326: curl_exec($ch);
327:
328: // cURLエラーチェック
329: if (curl_errno($ch)) {
330: // PHP8.5:非推奨関数
331: if (PHP_VERSION_ID < 80500) {
332: curl_close($ch);
333: }
334: return array(NULL, NULL);
335: }
336: $header = curl_getinfo($ch);
337: // PHP8.5:非推奨関数
338: if (PHP_VERSION_ID < 80500) {
339: curl_close($ch);
340: }
341:
342: // コンテンツ・サイズを求める
343: $size = $header['download_content_length'];
344: // HTTPステータスが200でサイズが求められなかった場合の処置
345: if (($header['http_code'] == 200) && ($size < 0)) {
346: $size = getContentsSize($url);
347: if ($size < 0) {
348: $options[CURLOPT_HEADER] = FALSE;
349: $ch = curl_init($url);
350: curl_setopt_array($ch, $options);
351: $res = curl_exec($ch);
352: // PHP8.5:非推奨関数
353: if (PHP_VERSION_ID < 80500) {
354: curl_close($ch);
355: }
356: $size = strlen($res);
357: }
358: }
359:
360: return array($header['http_code'], $size);
361: }
httpヘッダ は、配列 $http に格納しておく。getContext 関数同様、User-Agent や Referを偽装する。
cURL関数に設定するオプションは、コメントの通りである。CURLOPT_ENCODING は、コンテンツがgzipで圧縮されている場合に備えての指定である。
アクセスに成功したら、 curl_getinfo 関数で得られる download_content_length をコンテンツ・サイズとして返す。
もし、HTTPステータスコードが正常(200)なのに、この値が取得できなかった場合は、後述するユーザー定義関数 getContentsSize を使ってサイズを取得する。
解説:http上のファイルサイズ取得
check404.php
273: /**
274: * http上のファイルサイズ取得
275: * @param string $url 対象コンテンツ
276: * @param long ファイルサイズ
277: */
278: function getContentsSize($url) {
279: $data = '';
280: $context = getContext($url);
281: $fp = @fopen($url, 'r', FALSE, $context);
282: if (! $fp) return (-1);
283: while (! feof($fp)) {
284: $data .= fread($fp, 1024);
285: }
286: fclose($fp);
287:
288: return strlen($data);
289: }
ユーザー関数 getContext で生成したストリームコンテキストを使って、ブラウザからアクセスしているように見せかけて fopen 関数を実行し、[fread:phph_function] 関数を使ってコンテンツを読み込み、そのサイズを返す。
解説:URLを正規化する
まず、httpではじまるアドレスであれば絶対アドレスなので、即リターンする。
次に、基準となる絶対アドレス $sour と正規化するURLを結合し、変数 $url に再代入する。このとき、パス分離記号のスラッシュ "/" が二重にならないよう調整している。
この段階では、変数 $url の中に、相対パス指定を意味するドット . または .. が含まれている。続く処理で、スラッシュ "/" を目印にパスを分離し、ドット標記を消し込んでいく。
check404.php
175: /**
176: * URLを正規化する
177: * 相対アドレスを絶対アドレスに変換する
178: * @param string $url 正規化するURL
179: * @param string $sour 読み込んだコンテンツのURL(絶対アドレス)
180: * @return string 正規化したURL / FALSE(正規化に失敗;URLではない)
181: */
182: function normalizeURLs($url, $sour) {
183: // 前後の空白を除く
184: $url = trim($url);
185: // httpで始まればそのまま返す
186: if (preg_match('/^http/', $url) != FALSE) {
187: return $url;
188: }
189:
190: // 末尾のスラッシュを除く
191: $sour = rtrim($sour, '/');
192:
193: // 基準となる絶対アドレスと正規化するURLを結合する
194: if (preg_match('/\:\/\//', $url) == FALSE) {
195: $regs = parse_url($sour);
196: // URLとして分離できなければFALSE
197: if (!isset($regs['scheme']) || !isset($regs['host'])) {
198: return FALSE;
199: }
200: $dirname = isset($regs['path']) ? dirname($regs['path']) : '';
201: if (preg_match('/^\//', $url) > 0) {
202: $url = ltrim($url, '/'); // 冒頭のスラッシュは除く
203: $dirname = '';
204: }
205: $url = $regs['scheme'] . '://' . $regs['host'] . $dirname . '/' . $url;
206: }
207:
208: // ドット . または .. を置換する
209: $regs = parse_url($url);
210: // URLとして分離できなければFALSE
211: if (!isset($regs['scheme']) || !isset($regs['host'])) {
212: return FALSE;
213: }
214: $aa = preg_split("/[\/\\\]/", $regs['path']);
215: $an = count($aa);
216: $bb = array();
217: $bn = 0;
218: for ($i = 1; $i < $an; $i++) {
219: switch ($aa[$i]) {
220: case '.':
221: break;
222: case '..':
223: $bn--;
224: if ($bn < 0) return FALSE;
225: break;
226: default:
227: $bb[$bn] = $aa[$i];
228: $bn++;
229: break;
230: }
231: }
232: $ss = '';
233: for ($i = 0; $i < $bn; $i++) {
234: $ss = $ss . '/' . $bb[$i];
235: }
236:
237: return $regs['scheme'] . '://' . $regs['host'] . $ss;
238: }
解説:HTMLバリーデーション
| URL |
|---|
| https://validator.w3.org/nu/ |
check404.php
479: /**
480: * 指定したURLをHTMLバリーデーションする.
481: * W3C Markup Validator Web Service APIを利用する.
482: * @param string $url バリデーションするURL
483: * @return array(エラー数,警告数,情報数)/FALSE:APIコール失敗
484: */
485: function validateHTML($url) {
486: //W3C Markup Validator Web Service API
487: $webapi = 'https://validator.w3.org/nu/?';
488: //API引数
489: $params = array(
490: 'doc' => $url,
491: 'out' => 'json',
492: );
493: //HTTPヘッダ
494: $headers = array(
495: 'Content-Type: text/html; charset=UTF-8',
496: 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36',
497: );
498:
499: //W3C Markup Validator Web Service APIを呼び出す.
500: $options = array(
501: CURLOPT_URL => $webapi . http_build_query($params),
502: CURLOPT_RETURNTRANSFER => TRUE, // ホスト名の検証を無効化
503: CURLOPT_HTTPHEADER => $headers, // ヘッダ情報
504: CURLOPT_SSL_VERIFYPEER => FALSE, // SSL証明書の検証を無効化
505: CURLOPT_SSL_VERIFYHOST => FALSE, // ホスト名の検証を無効化
506: CURLOPT_FOLLOWLOCATION => TRUE, // リダイレクト先に自動アクセス
507: CURLOPT_AUTOREFERER => TRUE, // リダイレクト先にReferer設定
508: CURLOPT_MAXREDIRS => 10, // リダイレクトを追跡する最大回数
509: CURLOPT_CONNECTTIMEOUT => 120, // 接続開始までの最大待ち時間
510: CURLOPT_TIMEOUT => 120, // リクエスト終了までの最大時間
511: );
512: $ch = curl_init();
513: curl_setopt_array($ch, $options);
514: $response = curl_exec($ch);
515: // PHP8.5:非推奨関数
516: if (PHP_VERSION_ID < 80500) {
517: curl_close($ch);
518: }
519:
520: // エラーチェック
521: if ($response == FALSE) {
522: return FALSE;
523: }
524: // JSONデコード
525: $json = json_decode($response);
526:
527: // エラーチェック
528: if (! isset($json->messages)) {
529: return FALSE;
530: } else if (count($json->messages) == 0) {
531: return array(0, 0, 0);
532: }
533:
534: // エラー、警告、情報をカウントする.
535: $error = $warning = $info = 0;
536: foreach ($json->messages as $message) {
537: // エラー
538: if (preg_match('/error/ui', (string)$message->type) > 0) {
539: $error++;
540: // 警告
541: } else if (preg_match('/warning/ui', (string)$message->type) > 0) {
542: $warning++;
543: // 情報
544: } else if (preg_match('/info/ui', (string)$message->type) > 0) {
545: $info++;
546: }
547: }
548:
549: return array($error, $info, $warning);
550: }
解説:メイン・プログラム
なお、パラメータ取得時に、対象URLがURL文字列であるかどうか、"pahooInputData.php" にある validURL関数を使ってバリデーションする。
また、除外パターンを行分割して配列 $excludes に格納し、各要素に対して正規表現であるかどうかのバリデーションを行う。バリデーションを行うのは、以下に示すユーザー定義関数 validRegexPattern である。
check404.php
673: // メイン・プログラム ======================================================
674: // パラメータを取得する
675: $items = array();
676: $errmsg = '';
677: $htmlerror = $htmlwarning = $htmlinfo = '?';
678:
679: $flag = getParam('flag', FALSE, '');
680: $flag = ($flag == '1') ? FALSE : TRUE;
681: $checkhtml = getParam('checkhtml', FALSE, '');
682: $checkhtml = ($checkhtml == '1') ? TRUE : FALSE;
683: // URLのバリデーション
684: $url = getParam('url', FALSE, '');
685: if (isButton('exec') && (validURL($url, $errmsg) == FALSE)) {
686: $errmsg = $url . ' はURLではありません';
687: }
688:
689: // 除外パターンのバリデーション
690: $excludeList = NULL;
691: $exclude = getParam('exclude', FALSE, DEF_EXCLUDE);
692: if (isButton('exec') && ($exclude != '')) {
693: $excludes = explode("\n", $exclude);
694: foreach ($excludes as $key=>$val) {
695: $val = trim($val);
696: if ($val != '') {
697: if (validRegexPattern($val)) {
698: $excludeList[$key] = $val;
699: } else {
700: $errmsg = $val . ' は正規表現ではありません';
701: break;
702: }
703: }
704: }
705: if (count($excludeList) == 0) {
706: $excludeList = NULL;
707: }
708: }
709:
710: // 404チェックを実行する
711: if ($errmsg == '') {
712: $errmsg= ($url != '') ? check404($url, $items, $errmsg, XPATH_LIST, $excludeList) : '';
713: // HTMLバリデーションを行う。
714: if (($url != '') && ($errmsg == '') && $checkhtml) {
715: $arr = validateHTML($url);
716: if ($arr != FALSE) {
717: $htmlerror = $arr[0];
718: $htmlinfo = $arr[1];
719: $htmlwarning = $arr[2];
720: }
721: }
722: }
723:
724: // 表示HTMLを作成する
725: $HtmlBody = makeCommonBody($url, $items, $htmlerror, $htmlwarning, $htmlinfo, $errmsg, $flag, $checkhtml, $exclude);
726:
727: // 画面に表示する
728: echo $HtmlHeader;
729: echo $HtmlBody;
730: echo $HtmlFooter;
731:
732: /*
pahooInputData.php
535: /**
536: * 正規表現のバリデーションを行う.
537: * @参考URL https://www.pahoo.org/e-soul/webtech/php06/php05-23-01.shtm
538: * @param string $reg 正規表現;スラッシュ /.../ で囲むこと.
539: * @param string $text マッチングさせる文字列;デフォルトでは空文字
540: * @return bool TRUE:正規表現/FALSE:正規表現ではない
541: */
542: function validRegexPattern($reg, $text='') {
543: $res = @preg_match($reg, $text);
544: return ($res === FALSE) ? FALSE : TRUE;
545: }
参考サイト
- PHPでリンク切れを調べる(その2):ぱふぅ家のホームページ

この特徴を利用して、ホームページ内に書かれているリンク先が存在しているかどうか、存在する場合はコンテンツのサイズがゼロでないかどうかをチェックするプログラムを作ってみることにする。
あわせて、W3Cが提供するWebサービスを利用し、HTMLが文法的に正しいかをチェックする。
(2025年12月28日)PHP8.5対応:curl_closeを使わない
(2025年5月10日)getContext()--Referer生成機能追加, getHttpResponseCodeSize()--リクエストヘッダ改良