Как вы анализируете и обрабатываете HTML / XML в PHP? - PullRequest
2034 голосов
/ 26 августа 2010

Как можно проанализировать HTML / XML и извлечь из него информацию?

Ответы [ 30 ]

15 голосов
/ 31 мая 2011

Другой вариант, который вы можете попробовать - QueryPath . Он вдохновлен jQuery, но на сервере в PHP и используется в Drupal .

12 голосов
/ 15 ноября 2008

XML_HTMLSax довольно стабильно - даже если оно больше не поддерживается. Другой вариант может состоять в том, чтобы передать вам HTML через HTML Tidy и затем проанализировать его с помощью стандартных инструментов XML.

11 голосов
/ 03 июля 2014

Есть много способов обработки HTML / XML DOM, большинство из которых уже были упомянуты. Поэтому я не буду пытаться перечислить их сам.

Я просто хочу добавить, что лично я предпочитаю использовать расширение DOM и почему:

  • iit оптимально использует преимущество в производительности базового кода C
  • это OO PHP (и позволяет мне его подкласс)
  • это довольно низкий уровень (что позволяет мне использовать его как не раздутый фундамент для более продвинутого поведения)
  • обеспечивает доступ ко всем частям DOM (в отличие, например, от SimpleXml, который игнорирует некоторые из менее известных функций XML)
  • имеет синтаксис, используемый для сканирования DOM, аналогичный синтаксису, используемому в нативном Javascript.

И хотя мне не хватает возможности использовать селекторы CSS для DOMDocument, есть довольно простой и удобный способ добавить эту функцию: создание подклассов DOMDocument и добавление JS-подобных querySelectorAll и querySelector методов к Ваш подкласс.

Для анализа селекторов я рекомендую использовать очень минималистичный компонент CssSelector из Symfony framework . Этот компонент просто переводит селекторы CSS в селекторы XPath, которые затем могут быть переданы в DOMXpath для получения соответствующего Nodelist.

Затем вы можете использовать этот (все еще очень низкоуровневый) подкласс в качестве основы для более высокоуровневых классов, например, для. анализировать очень специфические типы XML или добавлять более jQuery-подобное поведение.

Приведенный ниже код идет прямо из моей библиотеки DOM-Query и использует описанную мной технику.

Для разбора HTML:

namespace PowerTools;

use \Symfony\Component\CssSelector\CssSelector as CssSelector;

class DOM_Document extends \DOMDocument {
    public function __construct($data = false, $doctype = 'html', $encoding = 'UTF-8', $version = '1.0') {
        parent::__construct($version, $encoding);
        if ($doctype && $doctype === 'html') {
            @$this->loadHTML($data);
        } else {
            @$this->loadXML($data);
        }
    }

    public function querySelectorAll($selector, $contextnode = null) {
        if (isset($this->doctype->name) && $this->doctype->name == 'html') {
            CssSelector::enableHtmlExtension();
        } else {
            CssSelector::disableHtmlExtension();
        }
        $xpath = new \DOMXpath($this);
        return $xpath->query(CssSelector::toXPath($selector, 'descendant::'), $contextnode);
    }

    [...]

    public function loadHTMLFile($filename, $options = 0) {
        $this->loadHTML(file_get_contents($filename), $options);
    }

    public function loadHTML($source, $options = 0) {
        if ($source && $source != '') {
            $data = trim($source);
            $html5 = new HTML5(array('targetDocument' => $this, 'disableHtmlNsInDom' => true));
            $data_start = mb_substr($data, 0, 10);
            if (strpos($data_start, '<!DOCTYPE ') === 0 || strpos($data_start, '<html>') === 0) {
                $html5->loadHTML($data);
            } else {
                @$this->loadHTML('<!DOCTYPE html><html><head><meta charset="' . $encoding . '" /></head><body></body></html>');
                $t = $html5->loadHTMLFragment($data);
                $docbody = $this->getElementsByTagName('body')->item(0);
                while ($t->hasChildNodes()) {
                    $docbody->appendChild($t->firstChild);
                }
            }
        }
    }

    [...]
}

См. Также Разбор XML-документов с помощью селекторов CSS , создатель Symfony Фабьен Потенциер (Fabien Potencier) о своем решении создать компонент CssSelector для Symfony и способы его использования.

11 голосов
/ 29 декабря 2011

Фреймворк Symfony имеет пакеты, которые могут анализировать HTML, и вы можете использовать стиль CSS для выбора DOMs вместо использования XPath .

9 голосов
/ 11 декабря 2015

С FluidXML вы можете запрашивать и выполнять итерацию XML с помощью XPath и CSS-селекторов .

$doc = fluidxml('<html>...</html>');

$title = $doc->query('//head/title')[0]->nodeValue;

$doc->query('//body/p', 'div.active', '#bgId')
        ->each(function($i, $node) {
            // $node is a DOMNode.
            $tag   = $node->nodeName;
            $text  = $node->nodeValue;
            $class = $node->getAttribute('class');
        });

https://github.com/servo-php/fluidxml

7 голосов
/ 16 октября 2013

JSON и массив из XML в три строки:

$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);

Та да!

7 голосов
/ 05 декабря 2013

Есть несколько причин не разбирать HTML по регулярному выражению.Но если у вас есть полный контроль над тем, какой HTML будет сгенерирован, то вы можете сделать это с помощью простого регулярного выражения.

Над ним находится функция, которая анализирует HTML с помощью регулярного выражения.Обратите внимание, что эта функция очень чувствительна и требует соблюдения HTML определенных правил, но она работает очень хорошо во многих сценариях.Если вам нужен простой парсер и вы не хотите устанавливать библиотеки, сделайте это:

function array_combine_($keys, $values) {
    $result = array();
    foreach ($keys as $i => $k) {
        $result[$k][] = $values[$i];
    }
    array_walk($result, create_function('&$v', '$v = (count($v) == 1)? array_pop($v): $v;'));

    return $result;
}

function extract_data($str) {
    return (is_array($str))
        ? array_map('extract_data', $str)
        : ((!preg_match_all('#<([A-Za-z0-9_]*)[^>]*>(.*?)</\1>#s', $str, $matches))
            ? $str
            : array_map(('extract_data'), array_combine_($matches[1], $matches[2])));
}

print_r(extract_data(file_get_contents("http://www.google.com/")));
2 голосов
/ 21 декабря 2017

Я создал библиотеку под названием HTML5DOMDocument, которая свободно доступна по адресу https://github.com/ivopetkov/html5-dom-document-php

Она также поддерживает селекторы запросов, которые, я думаю, будут чрезвычайно полезны в вашем случае.Вот пример кода:

$dom = new IvoPetkov\HTML5DOMDocument();
$dom->loadHTML('<!DOCTYPE html><html><body><h1>Hello</h1><div class="content">This is some text</div></body></html>');
echo $dom->querySelector('h1')->innerHTML;
0 голосов
/ 29 марта 2019

Лучший метод для разбора xml:

$xml='http://www.example.com/rss.xml';
$rss = simplexml_load_string($xml);
$i = 0;
foreach ($rss->channel->item as $feedItem) {
$i++;
echo $title=$feedItem->title;
echo '<br>';
echo $link=$feedItem->link;
echo '<br>';
if($feedItem->description !='') {$des=$feedItem->description;} else {$des='';}
echo $des;
echo '<br>';
if($i>5) break;
}
0 голосов
/ 16 августа 2018

Если вы знакомы с селектором jQuery, вы можете использовать ScarletsQuery для PHP

<pre><?php
include "ScarletsQuery.php";

// Load the HTML content and parse it
$html = file_get_contents('https://www.lipsum.com');
$dom = Scarlets\Library\MarkupLanguage::parseText($html);

// Select meta tag on the HTML header
$description = $dom->selector('head meta[name="description"]')[0];

// Get 'content' attribute value from meta tag
print_r($description->attr('content'));

$description = $dom->selector('#Content p');

// Get element array
print_r($description->view);

Для этой библиотеки обычно требуется менее 1 секунды для обработки автономного HTML.также принимать недопустимый HTML или отсутствующую цитату в атрибутах тега.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...