PHP . SU
Программирование на PHP, MySQL и другие веб-технологии
Описание: HTML-парсер с использованием xPath запросов и пользовательских фильтров.
Поиск в теме | Версия для печати
armancho7777777
Отправлено: 09 Ноября, 2013 - 19:51:58
Активный участник
Покинул форум
Сообщений всего: 4526
Дата рег-ции: Февр. 2011
Откуда: Москва
Помог: 221 раз(а)
Реализация (Отобразить ) PHP:
скопировать код в буфер обмена
/**
*
* @property-read string $text
* @property-read string $html
* @property-read string $className
* @property-read array $classList
* @property-read array $attrList
* @property-read object $data
*/
class parseHtmlElement extends DOMElement {
private $__data = NULL ;
private static $__fnFilter = NULL ;
public function __toString( ) {
return $this -> isBody ? $this -> html : $this -> ownerDocument -> saveHTML ( $this ) ;
}
public function __get( $name )
{
switch ( $name )
{
case ( 'className' ) :
return trim ( $this -> getAttribute ( 'class' ) ) ;
case ( 'classList' ) :
case ( 'attrList' ) :
{
foreach ( $this -> attributes as $name => $attrNode ) {
$attributes [ $name ] = $attrNode -> value ;
}
return $attributes ;
}
case ( 'text' ) :
return $this -> textContent ;
case ( 'html' ) :
{
$html = '' ;
foreach ( $this -> childNodes as $child ) {
$html .= $child -> ownerDocument -> saveHtml ( $child ) ;
}
return $html ;
}
case ( 'data' ) :
{
{
$this -> __data = new stdClass( ) ;
foreach ( $this -> attrList as $name => $value )
{
if ( preg_match ( '/^data-(?P<name>.+)$/siu' , $name , $attrData ) ) {
// Преобразование в верблюжью нотацию (camelCase).
$this -> __data-> { $name } = $value ;
}
}
}
return $this -> __data;
}
default :
return $this -> getAttribute ( $name ) ;
}
}
public static function filter( $item )
{
}
public function xPath( $query , $filter = NULL )
{
{
self :: $__fnFilter = $filter ;
$query .= '[php:function("' . get_class ( $this ) . '::filter", self::*)]' ; }
if ( $this -> isBody )
foreach ( $this -> xpath -> query ( $query , $this ) as $item ) {
$item -> xpath = $this -> xpath ;
$tesult [ ] = $item ;
}
return $tesult ;
}
}
/**
* @param string $html
* @param string $encoding
* @return parseHtmlElement
*/
function parseHtml( $html , $encoding = 'utf-8' )
{
$doc = new DOMDocument( '1.0' , $encoding ) ;
$doc -> registerNodeClass ( 'DOMElement' , 'parseHtmlElement' ) ;
$doc -> normalize ( ) ;
$xpath = new DOMXPath( $doc ) ;
$xpath -> registerNamespace ( "php" , "http://php.net/xpath" ) ;
$xpath -> registerPHPFunctions ( 'parseHtmlElement::filter' ) ;
$documentElement = $isBody
? $xpath -> query ( '//body[1]' ) -> item ( 0)
: $doc -> documentElement ;
$documentElement -> isBody = $isBody ;
$documentElement -> xpath = $xpath ;
return $documentElement ;
}
Примеры: (Отобразить ) PHP:
скопировать код в буфер обмена
$html = '<td class="low" colspan="3">
<span class="postal-code"><a href="url.php">Ссылка</a></span>
<span class="postal-code"><a href="url.php" class="test">Ссылка 2</a></span>
</td>' ;
// Пример 1
$result = parseHtml( $html ) -> xPath ( '/td[@class="low"]//a' ) ;
foreach ( $result as $item )
{
echo $item -> text , '<br>' ,
print_r ( $item -> attrList , 1 ) , '<br><br>' ; }
// Пример 2
$result = parseHtml( $html ) -> xPath ( '/td[@class="low"]' ) ;
foreach ( $result as $item )
{
// xPath запрос в контексте текущего элемента.
foreach ( $item -> xPath ( './/a' ) as $link )
{
echo print_r ( $link -> attrList , 1 ) , '<br>' ; }
}
// Примеры c пользовательским фильтром:
$result = parseHtml( $html ) -> xPath ( '/td[@class="low"]//a' , function ( $item ) {
return in_array ( 'test' , $item -> classList ) ;
} ) ;
// Отбираем все ссылки, которые начинаются с "http://"
$result = parseHtml( $html ) -> xPath ( '/td[@class="low"]//a' , function ( $item ) {
} ) ;
Свойства для чтения:
text - текст внутри элемента
html - html внутри элемента
attrList - массив атрибутов элемента
className - значение атрибута 'class'
classList - массив css-классов элемента
data - объект типа stdClass , содержащий данные атрибутов "data-*".
И сам элемент: $item->__toString()
Атрибута доступны так же в виде свойств.
Элементы возвращаемых массивов являются объектами типа parseElement , наследника класса DOMElement .
Можно расширить возможности класса DOMXPath путём наследования (или агрегации, если значения аргумента(ов) конструкторов отличаются), добавив метод cssQuery , реализовав для этого простейший конвертер css-селекторов в xPath-оси , или же воспользоваться классом Css2Xpath из пакета Zend\Dom\Query .(Отредактировано автором: 16 Октября, 2015 - 16:07:48)
bombording
Отправлено: 22 Ноября, 2013 - 11:14:14
Новичок
Покинул форум
Сообщений всего: 10
Дата рег-ции: Нояб. 2013
Помог: 0 раз(а)
armancho7777777
Сейчас тестирую Ваш скрипт.
Как можно разбить table tr на td элементы?
CODE (
html ):
скопировать код в буфер обмена
<table >
<tr ><td ></ td ><td ></ td ><td ></ td ><td ></ td ><td ></ td ></ tr >
<tr ><td ></ td ><td ></ td ><td ></ td ><td ></ td ><td ></ td ></ tr >
...
<tr ><td ></ td ><td ></ td ><td ></ td ><td ></ td ><td ></ td ></ tr >
<tr ><td ></ td ><td ></ td ><td ></ td ><td ></ td ><td ></ td ></ tr >
</ table >
Пробую:
Но выводится каждый td.
А мне необходимо создать массив из td элементов каждого tr.
armancho7777777
Отправлено: 22 Ноября, 2013 - 11:58:00
Активный участник
Покинул форум
Сообщений всего: 4526
Дата рег-ции: Февр. 2011
Откуда: Москва
Помог: 221 раз(а)
Решение похожей задачи реализовано во втором примере.
Метод
xPath возвращает массив объектов элементов DOM, у которых тоже есть метод
xPath .
Можно так ещё:
Если надо перевести значения массива в html-строку, то добавьте это:
(Отредактировано автором: 22 Ноября, 2013 - 14:43:51)
bombording
Отправлено: 22 Ноября, 2013 - 13:40:48
Новичок
Покинул форум
Сообщений всего: 10
Дата рег-ции: Нояб. 2013
Помог: 0 раз(а)
armancho7777777
Получилось. Здорово, скрипт выполняется около 4 секунд... аналогичный парсер DOM делал это 130 секунд.
Спасибо!
А можно, используя код ниже, загонять в массив данные без html... обычный текст.
Или все же нужно использовать strip_tags() после?
armancho7777777
Отправлено: 22 Ноября, 2013 - 14:20:01
Активный участник
Покинул форум
Сообщений всего: 4526
Дата рег-ции: Февр. 2011
Откуда: Москва
Помог: 221 раз(а)
bombording пишет: А можно, используя код ниже, загонять в массив данные без html... обычный текст.
Да. Вы не внимательны. Хотя разобрав примеры из первого поста Вы бы поняли.
Разберите уже их, а не просто копируйте.
Ещё пример:
PHP:
скопировать код в буфер обмена
function ( $tr ) {
function ( $td ) {
return $td -> html ; // Или $td->text;
} ,
$tr -> xPath ( './td' )
) ;
} ,
parseHtml( $html ) -> xPath ( '//tr' )
) ;
armancho7777777 пишет: Метод xPath возвращает массив объектов элементов DOM, у которых тоже есть метод xPath.
Так как объекты являются наследниками класса DOMElement, то соотвественно наследуют все его методы и свойства .
P.S.
bombording пишет: скрипт выполняется около 4 секунд
Чисто сам парсер съест доли секунд на небольшом документе.(Отредактировано автором: 18 Января, 2014 - 12:15:12)
Поиск в теме | Версия для печати
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Пользовательские функции »
Все гости форума могут просматривать этот раздел. Только зарегистрированные пользователи могут создавать новые темы в этом разделе. Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
Powered by ExBB FM 1.0 RC1. InvisionExBB