指定したフォルダにある.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;
}
}
}
}
?>
