Php търсачка във статични файлове

Hous

Registered
Здравейте, искам да попитам някой може ли да помогне как да стане търсене с php код но вместо в база данни, да е търсене във всички .html файлове в зададена папка? Искам да мога да търся сред всички тях, и ако може да търся в определен клас параграф (текста който е в него). Предполагам ме разбрахте? Също разбира се и ако може когато върна резултата самият линк да представлява името на намерения файл (или нещо подобно логически свързано за да създам линк).
 
Колега, взимаш файловете от папката в един масив, правиш foreach на масива и след това един preg_match_all с думата или символа, който търсиш и си готов.
 
1. Взимаш файловете от папката с пълния им път -> 2.
2. Четеш файла -> 2.1.
2.1. с preg_match_all търсиш това, което те интересува -> ако не го намериш 2.2., -> ако го намериш 3.
2.2. затваряш текущия файл и отваряш следващия, ако има следващ -> 2.1., ако няма следващ -> 5
3. Запазваш в променлива последната итерация(файла, който си преглеждал) и данните, които си намерил -> 4
4. Използваш си данните, както си искаш -> 5
5. Край

Кратко описание на алгоритъма.
 
Благодаря за отговорите. На теория знам как да стане. Въпроса ми беше да видя примерен код. И @revelation ако намеря това което търся все пак е хубаво да проверя и в другите файлове защото може да имам повече от един резултат :) Също и ми трябва линк към файла и preg_match_all да бъде само в определен параграф (с даден клас) за да не търся целия файл.
 
Ами в такъв случай просто пъхаш резултата в един масив и продължаваш да търсиш напред. (ключ - линк към файла, стойност - търсения резултат)

Дай примерен файл, ако има нещо специфично, което трябва да се парсва.
 
Ами примерен файл: file1.html
Вътре:
Код:
<html>
<head></head>
<body>
 <div class="simple-article">
Here is the text that I need to search, we might have few tags not just pure text
</div>
</body>
</html>

Примерна директория с файловете /cat1/ или /cat2/ (няколко такива папки с по 5-6 файла)
 
Hous каза:
Ами примерен файл: file1.html
Вътре:
Код:
<html>
<head></head>
<body>
 <div class="simple-article">
Here is the text that I need to search, we might have few tags not just pure text
</div>
</body>
</html>

Примерна директория с файловете /cat1/ или /cat2/ (няколко такива папки с по 5-6 файла)
Ако са много файловете и наистина са статични защо не вкараш в БД само това за което се търси?
 
Защото не искам да имам mysql и ще се ползва доста малко php, за това реших да се търси директно в тях, а и като се променя ще се променя само във файла.
 
Hous каза:
Благодаря за отговорите. На теория знам как да стане. Въпроса ми беше да видя примерен код. И @revelation ако намеря това което търся все пак е хубаво да проверя и в другите файлове защото може да имам повече от един резултат :) Също и ми трябва линк към файла и preg_match_all да бъде само в определен параграф (с даден клас) за да не търся целия файл.

Ти така или иначе трябва да провериш целия файл, за да стигнеш до този ред, който искаш. Но ти с всеки пост, все повече усложняваш задачата.

Файловете еднакви ли са на вид.
Има ли вариант в един файл да имаш няколко параграфа(div или p)
Файловете ти ли ги създаваш или ги взимаш от някъде(ако ти ги създаваш и ще ги ползваш само с тази цел да ги парсваш, то по-добре си създай някакъв шаблон за по-лесно индициране на реда, който ти трябва).

Защо трябва да е от определен параграф. Има ли вариант в няколко параграфа да има едно и също нещо ?

Обясни по-подробно, за да ти се помогне, тя парсващата част е най-задълбочена, останалото е нищо. Или обясни първо какво точно искаш да направиш.
 
Ами файловете са .html аз ще ги създавам, те са си шаблон, ще ми трябва търсенето да става в определен клас sample-post. Ще имам няколко папки и в тях сравнително малко файлове (няма да са вероятно повече от 30-40 файла общо). И идеята е да направя един php скрипт с който да отварям файловете и да ги търся, когато намеря това което се търси да върна част от изречението и линк към името на файла (разбира се от fail1.html ще стане test.com/papka/fail-1/) Това е идеята.
 
Ами шаблона по този начин е труден за парсване. В смисъл има доста по-лесни варианти.

simple-post:Text-text-text-text (new line)
simple-post2:Text-text-text-text

Така е по-лесно да се намери реда и да се търси единствено от него. Ако смяташ, че можеш да си позволиш промяна на шаблона ще е доста добре, иначе ще стане малко по-голямо мазало.

Довечера ще гледам да ти дам код, ти пиши дали можеш да си промениш шаблона да знам как да парсвам.
 
Ами под шаблон имах предвид, че всичко е еднотипно освен title,links и текста в самия
Код:
<div class="sample-post">
 
PHP:
<?php

$dir = "D:\\wamp\\www\\WT\\testDir\\";

function parse_dir($dir) 
{
	$directoryList = [];
	
	if (is_dir($dir)) {
		if ($dh = opendir($dir)) {
			while (($file = readdir($dh)) !== false) {
				if ( filetype($dir.$file) == 'file' && strstr($file, 'html') ) {
					$directoryList[] = $dir . $file;
				}
			}
			closedir($dh);
		}
	}
	
	return $directoryList;
}

function file_parser($dir, $class, $needed)
{
	$data = [];
	$directories = parse_dir($dir);
	
	if  ( sizeof($directories) > 0 ) 
	{
		foreach ( $directories as $dir )
		{
			if ( is_file($dir) )
			{
				$readFile = file_get_contents($dir);
				preg_match_all('#<(div|p)\s*class="' . $class . '"\s*>\n?.*(' . $needed . ').*\n?<\/(div|p)>#i', $readFile, $matches);
				
				if ( sizeof($matches[2]) ) {
					$data[] = ['link' => $dir, 'target' => $matches[2][0]];
				}
			}
		}
		
		return $data;
	}
}

print_r(file_parser($dir, 'simple-article', 'i need'));

Файлове в папка testDir са ми двата file1.html и file2.html

Резултат:

PHP:
Array
(
    [0] => Array
        (
            [link] => D:\wamp\www\WT\testDir\file1.html
            [target] => I need
        )

    [1] => Array
        (
            [link] => D:\wamp\www\WT\testDir\file2.html
            [target] => I need
        )

)

Ето ти пробен скрипт. Най-горе си задаваш папката.

Използваш file_parser() като за:

Параметър 1: подаваш пълния път на директорията
Параметър 2: указваш класа, за който да търси(ще търси само за p и div тагове - пример: <div class="simple-article">...</div>)
Параметър 3: Указват това, което търсиш

Задал съм да търси само в html файлове. Ако не искаш махни strstr($file, 'html') от parse_dir() функцията.
Надявам се да съм бил полезен.
 
Странно но ми дава грешка при
Код:
$directoryList = [];
Syntax error unexpected '['
или ако го махна дава на
Код:
$data = [];

Също така как да стане номера ако искам да търси в няколко директории?
 
Hous каза:
Странно но ми дава грешка при
Код:
$directoryList = [];
Syntax error unexpected '['
или ако го махна дава на
Код:
$data = [];

Също така как да стане номера ако искам да търси в няколко директории?

Хаха, ами квадратните скоби ги смени на array() защото явно си с по-стара версия на PHP и това не фигурира при теб.

Ами принципно мога да модифицирам скрипта да приема масив от директории, както и да получава масив от различни класове(ако има нужда). Другия вариант е просто да си вкараш в един масив директориите и да въртиш цикъл с file_parser като подаваш директорията на първия аргумент.

ЕДИТ: ['link' => $dir, 'target' => $matches[2][0]] - това го смени на array('link' => $dir, 'target' => $matches[2][0])

ЕДИТ 2: Ако директориите са в поддиректории на една директория, то мога да променя скрипта да взима директориите и файловете рекурсивно.
 
Php-то ми е уж ново (суперхостинг) но както и да е. Иначе проверката за html файл не сработва нещо
Код:
Warning: filetype() [function.filetype]: Lstat failed for .test.html in /home/test/public_html/test.com/search.php on line 93
Иначе директориите ще са в главната директория на сайта и ще е добре да ги сложа в масив може би да ги обхожда и всички файлове в тях.
Примерка структура:
public_html/sait.com/papka1/
file1.html
public_html/sait.com/papka2/
file2.html file3.html file4.html
public_html/sait.com/papka3/
file5.html

И идеята е да си е работеща търсачка, която да търси в класът, които дадох за пример и да мога да отворя файла
sait.com/papka1/file1.html (ако да кажем в него има резултат)

Малко сложно звучи но е както другите търсачки, просто да не е в DB
 
PHP:
<?php
function parse_dir($path, $name) 
{
	$data = array();

	for ($i=0; $i < 5; $i++) {
		  $res = glob("{$path}{$name}");
		  if (count($res)) {
				$data[] = $res;
				break;
		  }
		  $path .= '*/';
		  //echo "\t{$path}<br>"; // Debug output
	}
	return $data[0];
}

function file_parser($dir, $needed, $tags, $class)
{
	$data = array();
	// търсим всичи файлове, които са с разширение .html
	$directories = parse_dir($dir, '*.html');
	
	if  ( sizeof($directories) > 0 ) 
	{
		foreach ( $directories as $dir )
		{
			if ( is_file($dir) )
			{
				$readFile = file_get_contents($dir);
				preg_match_all('#<(' . implode('|', $tags) . ')\s*(class="(' . implode('|', $class) . ')")?\s*>\n?.*(' . $needed . ').*\n?<\/(' . implode('|', $tags) . ')>#i', $readFile, $matches);
				
				if ( sizeof($matches[4]) ) {
					$data[] = array('link' => $dir, 'target' => $matches[4][0]);
				}
			}
		}
		
		return $data;
	}
}

$dir = "D:/wamp/www/WT/testDir/";
$needed = "i need";
$tags = array('div', 'p');
$class = array('simple-post', 'simple-article');

echo "<pre>";
print_r(file_parser($dir, $needed, $tags, $class));

Ето ти промяната, като приемам, че директориите са в една поддиректория.

PHP:
- dir/
-- dir1/
--- file1.html
--- file2.html
-- dir2/
--- file1.html

Добавих и да търси в различни тагове и различни класове.

1 параметър е директорията, където да търси.
2 параметър е това, което търсиш
3 параметър са таговете, в които да търси
PHP:
$tags = array('div', 'p');
4 параметър са класовете, в които да търси. Ако не е зададено нищо, както и по дефолт ще търси, ако няма зададен клас
PHP:
$classes = array('simple-article', 'simple-post');

Варианти, в които ще търси(същото и с <p> )

PHP:
<div>
text-text
</div>

<div class="simple-post">
text-text
</div>

<div class="simple-article">
text-texte
</div>
 
Не връща резултат, проверих директорията (принципно използвам "." или пълният път) обаче като опитам да дебъгна (твоя коментар) връща само array ()

това
Код:
$path="*/";
май е впроблем в случая
 
В теб е проблема някъде. Даваш ми твърде съкратена информация в това, къде ти мислиш, че е проблема.
Не е в това, което ти посочваш.

При мен си работи, нещо ти не правиш, както трябва.

Дай повече информация как ползваш функцията.
 

Back
Горе