суббота, 19 октября 2019 г.

Поиск на сайте определенных строк

Данный php скрипт парсит карту сайта (в формате XML) и ищет на страницах интересующие нас последовательности символов. Например, если надо найти все страницы, которые содержат ссылки на админку, или файлы .js, или .php, и так далее. В частности, мне надо было найти, ссылаются ли страницы сайта (коих примерно 17 тысяч) на папку /includes и некоторые другие поддиректории корневой директории.

Код:


ini_set("display_errors", "1"); // выводим ошибки php
error_reporting(E_ALL);

$time_start = microtime(true);

// SETTING
$log_file = 'scan_sitemap_log.log';
$sitemap = __DIR__."/../../"."sitemap_xml_0.xml";
$patterns = array('administrator', 'bin/', 'cache/', 'cgi-bin/', 'cli/', 'includes/', 'language/', 'layouts/', 'libraries/', 'myscripts/', 'tmp/', '.php');
$max_pages = 100;
$sleep = 2;

function logSave() {
    global $log_file, $log_text;
    $log_text = date('Y-m-d H:i:s', time()) . " (UTC) ".$log_text;
    file_put_contents(__DIR__.'/'.$log_file, trim($log_text).PHP_EOL, FILE_APPEND);
    $log_text = '';
}

// Очистим предыдущий лог
$clean = unlink(__DIR__.'/'.$log_file);
if ($clean) {
    $log_text = 'Почистили лог';
    logSave();
}

// спарсим карту сайта
if (file_exists($sitemap)) {
    $xml = simplexml_load_file($sitemap);
} else {
    $log_text = "Не удалось открыть файл $sitemap";
    logSave();
}

if (count($xml->url) > 0) {
    $i = 0;
    foreach ($xml->url as $item) {
        if ($i > $max_pages) break;
        
        $url = $item->loc;
        $log_text = "Нашли url $url";
        logSave();
        // получим код страницы
        $html = file_get_contents($url);
        foreach ($patterns as $pattern) {
            if (preg_match("/".str_replace('/', '\/', preg_quote($pattern))."/i", $html)) {
                $log_text = "В коде страницы содержится $pattern";
                logSave();
            }
        }
        sleep($sleep);
        $i++;
    }
}

function word_variation_rus($chislo, $mnogo, $odin, $dva) {
    // @author Alexey Gnevyshev
    $ost_10  = $chislo%10;
    if ($ost_10 == 0 || $ost_10 >= 5 || in_array($chislo%100, range(11,19))) $string_txt = "$chislo $mnogo";
    else {
        if ($ost_10 == 1) $string_txt = "$chislo $odin";
        else if (in_array($ost_10, range(2,4))) $string_txt = "$chislo $dva";
    }
    return $string_txt;
}

$time_end = microtime(true);
$time = round($time_end - $time_start, 2);
if ($time / 3600 >= 1) {
    $chasov = floor($time / 3600);
    $minut = floor(($time%3600) / 60);
    $sekund = $time%60;
    $time = word_variation_rus($chasov, 'часов', 'час', 'часа').' '.word_variation_rus($minut, 'минут', 'минута', 'минуты')." $sekund сек.";
}
else if ($time / 60 >= 1) {
    $minut = floor($time / 60);
    $sekund = $time%60;
    $time = word_variation_rus($minut, 'минут', 'минута', 'минуты')." $sekund сек";
}
else {
    $time = $time." сек";
}
$log_text = "Обход завершён. Затрачено: $time.";
logSave();


Подразумеватся, что на хостинге есть поддержка SimpleXML.

Скрипт работает с паузами, чтобы сильно не нагружать хостинг. Лучше запускать либо через крон (задача на выполнение php скрипта), либо конретный запуск php, но не через http(s) протол, т.к. там обычно время отдачи ограничено. Для парсинга надо больше.

Результаты парсинга будут в файле лога, указанном в настройках.

Блок SETTING подразумеват некоторые предварительные настройки скрипта. $max_pages устанавливает, сколько страниц сканировать (иногда достаточно 100 страниц, например, чтобы долго не ждать). Если что-то непонятно, можете обратиться в комментариях, обычно стараюсь ответить.

Комментариев нет:

Отправить комментарий