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”).

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

Использование парсера на основе регулярных выражений позволяет сделать более гибкое решение, но оно требует хороших знаний. Учите матчасть!
Добавлено: 20 Августа 2013 01:41:18 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...