指定したフォルダにある.htmlファイルおよび子フォルダ内にある.htmlファイルを再帰検索して、
指定した検索文字列が存在するヒットした結果を表示するPHPソースコード。
検索ボタンが押される度に.htmlファイルを探索して文字列を探索するため、数百ファイルの検索が限界だと思われます。
DBを使っていないので、以下ソースをsearch.phpなどのファイル名でドキュメントルートに設置し、ブラウザからアクセスするだけで稼働します。
大きなサイトに対応するためには夜間バッチでDBのテーブルにコンテンツを登録するなどの工夫が必要。
サンプル
本サイトの大半はhtmlファイル(500ページくらい)で作成されていますので、下記サンプルを使用してサイト内検索が可能です。
自サイト内検索を使用してみる
PHPソースコード
<?php date_default_timezone_set("Asia/Tokyo"); mb_regex_encoding("UTF-8"); mb_language("Japanese"); mb_internal_encoding("UTF-8"); setlocale(LC_ALL, 'ja_JP.UTF-8'); mb_regex_encoding("UTF-8"); //------------------------------------------------------------ //.htmlファイルの探索の最上位フォルダ $basedir=__DIR__.DIRECTORY_SEPARATOR; //上記フォルダのURL $filepath = pathinfo($_SERVER["REQUEST_URI"]); $baseurl=substr($_SERVER["REQUEST_URI"],0,strlen($_SERVER["REQUEST_URI"])-strlen($filepath['basename'])); //検索ページのタイトル $search_name='サイト内検索'; //検索ページからトップページへのリンクの表示名 $topname='トップページへ'; //検索ページからトップページへのリンクURL $topurl='/'; //------------------------------------------------------------ $word=''; if(isset($_REQUEST["word"])){ $word=$_REQUEST["word"]; $word=trim(mb_convert_encoding($word,"UTF-8","UTF-8,SJIS,JIS,EUC-JP")); $word=mb_convert_kana($word,'aKsV','UTF-8'); $word=htmlentities($word); } $html_head=<<<EOT <!DOCTYPE html> <html lang="ja"> <head> <meta http-equiv="content-language" content="ja"> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1, maximum-scale=1, user-scalable=no"> <title>{$search_name}</title> <style> body{font-size:16px;color:#333;padding:1em;margin:0.5em;} h1{font-size:1.5em;margin:0;padding:0.2em;} .redbold{color:red;font-weight:bold;} .datefmt{font-size:0.6em;margin:0;padding:0.1em;} .hit_text{font-size:1em;margin:0;margin-inline:0;white-space: pre-wrap;word-wrap: break-word;} .search_result{width:100%;margin-bottom:2em;} </style> </head> <body> EOT; $html_header=<<<EOT <header><h1>{$search_name}</h1></header> <main> EOT; $html_back=<<<EOT <div style="text-align:right;"><a href="{$topurl}">{$topname}</a></div> EOT; $html_form=<<<EOT <form action="{$_SERVER["REQUEST_URI"]}" method="post" id="search_form" style="width:100%;"> <label for ="word">検索文字列:</label> <input type="text" name="word" value="{$word}" maxlength="100" id="word" style="width:50%;" /> <input type="submit" value="検索" /> </form> EOT; $html_foot =<<<EOT </main> <footer></footer> </body> </html> EOT; if(!isset($word)||$word==""){ echo $html_head; echo $html_header; echo $html_back; echo $html_form; echo $html_foot; }else{ $word_arr=mb_split(" ",$word); for($i=count($word_arr)-1;$i>=0;$i--){ if($word_arr[$i]==""){ array_splice($word_arr,$i,1); } } $files=[]; //.htmlファイルの探査 searchHtmlFile($basedir,$baseurl,$files); $matchFiles=[]; $html=""; foreach($files as $file){ $buf=""; $buf=file_get_contents($file["path"]); $buf=@mb_convert_encoding($buf,"UTF-8","ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN,SJIS"); $buf=str_replace(["\r\n","\r","\n"],'',$buf); $buf=str_replace([' ',' ',"\t"],'',$buf); if(preg_match("/<title[^>]*?>(.*?)<\/title>/i", $buf, $tmp)==1){ $title=trim($tmp[1]); }else{ $title=""; } $flag=false; if(preg_match("/<body[^>]*?>(.*?)<\/body>/i", $buf, $tmp)==1){ $body=$tmp[1]; $flag=true; } if($flag){ $body = preg_replace('/<style.*?>.*?<\/style.*?>/is', '', $body) ; $body = preg_replace('/<script.*?>.*?<\/script.*?>/is', '', $body) ; $body = preg_replace('/<!--.*?-->/is', '', $body) ; $body=strip_tags($body); //$body=html_entity_decode($body); $body=mb_convert_kana($body,'aKSV','UTF-8'); $count=0; foreach($word_arr as $val){ if(mb_stripos($title.$body,$val)===false){ $flag=false; break; }else{ //$count+=mb_substr_count($title.$body,$val); } } if($flag){ $pos=mb_stripos($title.$body,$word_arr[0]); $l=mb_strlen($word_arr[0]); $pos1=$pos-50; if($pos1<0){$pos1=0;} $pos2=$pos+$l+50; if($pos2>(mb_strlen($body))){$pos2=mb_strlen($body);} $body_m=mb_substr($body,$pos1,$pos2-$pos1); foreach($word_arr as $val){ $body_m=str_ireplace($val,'<span class="redbold">'.$val.'</span>',$body_m); } if($title==""){$title=mb_substr($body,0,10); /*$title="タイトル無";*/} $matchFile=[]; $matchFile["url"]=$file["url"]; $matchFile["title"]=$title; $matchFile["body"]=$body_m; $matchFile["name"]=$file["name"]; $matchFile["date"]=$file["date"]; //$matchFile["count"]=$count; $matchFiles[]=$matchFile; } } } //ファイルの更新日順に並べる $order=[]; foreach($matchFiles as $val){ $order[]=$val["date"]; } arsort($order); $results=[]; foreach($order as $key=>$val){ $results[]=$matchFiles[$key]; } echo $html_head; echo $html_header; echo $html_back; echo $html_form; echo "<h4>"; foreach($word_arr as $wd){echo "「".$wd."」";} echo " の検索結果:".count($matchFiles)."件</h4>"."\n"; if(count($matchFiles)>0){ foreach($results as $result){ echo '<div class="search_result">'."\n"; echo ' <div><a style="" href="'.$result["url"].'">'.$result["title"].'</a></div>'."\n"; echo ' <div>'."\n"; echo ' <p class="datefmt">更新日:<time>'.$result["date"].'</time></p>'."\n"; echo ' <p class="hit_text">'.$result["body"].'</p>'."\n"; echo ' </div>'."\n"; echo "</div>\n"; } }else{ echo "<div>見つかりませんでした</div>\n"; } echo $html_back; echo $html_foot; } //.htmlファイルの再帰探査 function searchHtmlFile($basedir,$baseurl,&$files){ foreach( new DirectoryIterator($basedir) as $fileinfo ) { if($fileinfo->isDir()){ if($fileinfo->getFilename() !=='.' && $fileinfo->getFilename() !== '..'){ searchHtmlFile( $basedir.$fileinfo->getFilename().DIRECTORY_SEPARATOR, $baseurl.$fileinfo->getFilename().'/', $files ); } }else{ if($fileinfo->getExtension()==='html'){ $file=[]; $file["path"]=$basedir.$fileinfo->getFilename(); $file["url"]=$baseurl.$fileinfo->getFilename(); $file["name"]=$fileinfo->getFilename();; $file["date"]=Date("Y/m/d H:i:s",$fileinfo->getMTime()); $files[]=$file; } } } } ?>