PHP

Как сделать простой скрепер на PHP без регулярных выражений.

Веб скреперы - это простые программы, которые используются для того, чтобы извлечь определенные данные с веб страниц. Обычно структура страниц известна, таким образом скреперы имеют менее сложные алгоритмы работы по сравнению с парсерами.

В данном уроке мы создадим простой скрепер, который получает заголовок и фавикон с HTML страницы.

Обычно скреперы основаны на использовании регулярных выражений, но в данном уроке мы будем их избегать. Вместо них будут использоваться простые строковые функции PHP.

Предположим, что все страницы, которые мы собираемся обработать скрепером, имеют следующую структуру:
<html>
<title>Заголовок страницы | Имя сайта</title>
<link rel="shortcut icon" href="http://www.site.com/favicon.ico"/>
...
<body>
...
<h1>Title</h1>
...
</body>
 
</html>

Мы собираемся получить заголовок и фавикон из секции meta, а если заголовок отсутствует, то будем искать тег h1 в разделе body. Данные операции могут быть выполенены с использованием только двух функций.
function strInBetween($text,
                      $separatorStart,
                      $separatorEnd,
                      &$positionOut = null,
                      $after = null,
                      $afterIndex = 0)
{
    $CYCLE_LIMIT = 500;
 
    $stop = false;
    $pos = 0;
    $current = strInBetween($text, $separatorStart, $separatorEnd, $pos);
    $matching = strpos($current, $containing);
    $i = 0;
    $afterIndex = 0;
    while ($pos >= 0 && $matching === false && $i < $CYCLE_LIMIT)
    {
        $afterIndex += $pos + strlen($current);
        $current = strInBetween($text, $separatorStart, $separatorEnd, $pos, null, $afterIndex);
        $matching = strpos($current, $containing);
        $i++;
    }
 
    if ($matching)
        return $current;
    else
        return null;
}

Данная функция возвращает первую подстроку, найденную в аргументе $text, заключенную в два разделителя: $separatorStart и $separatorEnd. Опционально, другая подстрока или индекс могут быть определены для начала поиска после них:

$text - текст, где ищется подстрока
$separatorStart - разделитель строки слева
$separatorEnd - разделитель строки справа
&$positionOut - опциональный параметр вывода, содержит позицию, где находится подстрока.
$after - опциональный параметр, если определен, то поиск будет проводиться после подстроки $after
$afterIndex - опциональный параметр, используется если $after имеет значение null. Содержит индекс, с которого надо начинать поиск.
function strInBetweenContaining($text,
                               $separatorStart,
                               $containing,
                               $separatorEnd,
                               &$pos = null,
                               $after = null,
                               $afterIndex = 0)
{
    if ($after != null)
    {
        $pos = strpos($text, $after);
        if ($pos !== false)
            $afterIndex = $pos;
    }
 
    $start = -1;
    $pos = strpos($text, $separatorStart, $afterIndex);
    if ($pos !== false)
        $start = $pos;
 
    $end = -1;
    $pos = strpos($text, $separatorEnd, $start + strlen($separatorStart));
    if ($pos !== false)
        $end = $pos;
 
    if ($start < 0 && $end < 0)
    {
        if ($positionOut != null)
            $positionOut = -1;
 
        return null;
    }
    else
    {
        if ($positionOut != null)
            $positionOut = -1;
 
        return substr($text, $start + strlen($separatorStart), $end - ($start + strlen($separatorStart)));
    }
}

strInBetweenContaining основана на предыдущей функции. Она возвращает строку только если она содержит заданную подстроку.

А это код скрепера:
require_once('util/getpage.php');
require_once('util/stringutils.php');
 
$url = $_GET['u'];
$page = getpage($url);
 
function getTitle($page) { return strInBetween($page, '<title>', '</title>'); }
function getH1($page) { return strInBetween($page, '<h1', '</h1>'); }
function getLink($page)
{
    $block = strInBetweenContaining($page, '<link', 'rel="shortcut icon"', '/>');
    return strInBetween($block, 'href="', '"');
}
 
echo getTitle($page) . '<br>';
echo strip_tags('<h1' . getH1($page)) . '<br>';
 
$favicon = getLink($page);
if ($favicon == null)
    $favicon = $url . 'favicon.ico';
 
//echo $favicon;
echo "<img src='$favicon' />";

Код достаточно простой и очевидный. Извлекается заголовок и первый тег h1, а затем наступает очередь фавикона. Если фавикон для страницы не найден, то код возвращает используемый по умолчанию (в соответствии с условиями в корневом каталоге сайта должен располагаться “favicon.ico”).

В данном примере продемонстрировано, что получить пару значений из кода страницы можно с использованием простого алгоритма. Его можно повторно использовать и расширить для вытаскивания любых данных с веб страницы.

Использование парсера на основе регулярных выражений позволяет сделать более гибкое решение, но оно требует хороших знаний. Учите матчасть!
Теги:
скрепер
Добавлено: 04 Мая 2018 08:40:49 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...