';
echo '2, 3, 5, 7, ';
while (true) {
$t = 6;
while (true) {
if ($n % ($t - 1) == 0) {
break;
}
if ($n % ($t + 1) == 0) {
break;
}
if ($t > sqrt($n)) {
echo("$n, ");
break;
}
$t += 6;
}
if (($n + 1) % 6 == 0) {
$n += 2;
} else {
$n += 4;
}
if ($n > $o) {
break;
}
}
?>
Для HTML5 html5 lib был оставлен уже много лет. Единственная библиотека HTML5, которую я могу найти с недавними записями обновления и обслуживания, - это html5-php , который чуть больше недели назад был добавлен в бета 1.0.
Сторонние альтернативы SimpleHtmlDom, которые используют DOM вместо String Parsing: phpQuery , Zend_Dom , QueryPath и FluentDom .
JSON и массив из XML в трех строках:
$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
Ta da!
Advanced Html Dom - это простая замена HTML DOM , которая предлагает один и тот же интерфейс, но это DOM-based, что означает, что ни одна из связанных проблем с памятью не возникает.
Он также имеет полную поддержку CSS, включая расширения jQuery .
Для 1a и 2: я проголосовал бы за новый класс DOMCrawler класса Symfony ( DomCrawler ). Этот класс позволяет запросы, похожие на CSS Selectors. Взгляните на эту презентацию для реальных примеров: news-of-the-symfony2-world .
Компонент предназначен для автономной работы и может использоваться без Symfony.
Единственным недостатком является то, что он будет работать только с PHP 5.3 или новее.
Существует несколько причин не анализировать 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/")));
Я создал библиотеку с именем PHPPowertools / DOM-Query , которая позволяет обходить HTML5 и XML-документы так же, как и с jQuery.
Под капотом используется symfony / DomCrawler для преобразования селекторов CSS в селектора XPath .
namespace PowerTools;
// Get file content
$htmlcode = file_get_contents('https://github.com');
// Define your DOMCrawler based on file string
$H = new DOM_Query($htmlcode);
// Define your DOMCrawler based on an existing DOM_Query instance
$H = new DOM_Query($H->select('body'));
// Passing a string (CSS selector)
$s = $H->select('div.foo');
// Passing an element object (DOM Element)
$s = $H->select($documentBody);
// Passing a DOM Query object
$s = $H->select( $H->select('p + p'));
// Select the body tag
$body = $H->select('body');
// Combine different classes as one selector to get all site blocks
$siteblocks = $body->select('.site-header, .masthead, .site-body, .site-footer');
// Nest your methods just like you would with jQuery
$siteblocks->select('button')->add('span')->addClass('icon icon-printer');
// Use a lambda function to set the text of all site blocks
$siteblocks->text(function( $i, $val) {
return $i . " - " . $val->attr('class');
});
// Append the following HTML to all site blocks
$siteblocks->append('<div class="site-center"></div>');
// Use a descendant selector to select the site's footer
$sitefooter = $body->select('.site-footer > .site-center');
// Set some attributes for the site's footer
$sitefooter->attr(array('id' => 'aweeesome', 'data-val' => 'see'));
// Use a lambda function to set the attributes of all site blocks
$siteblocks->attr('data-val', function( $i, $val) {
return $i . " - " . $val->attr('class') . " - photo by Kelly Clark";
});
// Select the parent of the site's footer
$sitefooterparent = $sitefooter->parent();
// Remove the class of all i-tags within the site's footer's parent
$sitefooterparent->select('i')->removeAttr('class');
// Wrap the site's footer within two nex selectors
$sitefooter->wrap('<section><div class="footer-wrapper"></div></section>');
[...]
Библиотека также включает собственный автозагрузчик с нулевой конфигурацией для совместимых с PSR-0 библиотек. Приведенный пример должен работать из коробки без какой-либо дополнительной настройки. Кроме того, вы можете использовать его с композитором.
Почему вы не должны и , когда вы должны использовать регулярные выражения?
Во-первых, обычное неправильное выражение: регулярные выражения не предназначены для «синтаксического анализа» ] HTML. Regexes может, однако, «извлечь» данные. Извлечение - это то, для чего они созданы. Основным недостатком выработки HTML-выражения в правильных инструментариях SGML или базовых синтаксических анализаторов XML является их синтаксическое усилие и различная надежность.
Считайте, что создание несколько надежного HTML-выражения regex:
<a\s+class="?playbutton\d?[^>]+id="(\d+)".+? <a\s+class="[\w\s]*title
[\w\s]*"[^>]+href="(http://[^">]+)"[^>]*>([^<>]+)</a>.+?
является менее читаемым, чем простой эквивалент phpQuery или QueryPath:
$div->find(".stationcool a")->attr("title");
Существуют, однако, конкретные варианты использования, в которых они могут помочь.
<!--
, которые иногда являются более полезными якорями для извлечения. В частности, псевдо-HTML-вариации <$var>
или SGML-остатки легко приручить с регулярными выражениями. Иногда даже желательно предварительно извлечь фрагмент HTML с использованием регулярных выражений /<!--CONTENT-->(.+?)<!--END-->/
и обработать остаток, используя более простые интерфейсы парсера HTML.
Примечание. У меня на самом деле есть это приложение , где я использую разбор XML и регулярные выражения альтернативно. На прошлой неделе разразился синтаксический анализ PyQuery, и регулярное выражение все еще работало. Да, странно, и я не могу объяснить это сам. Но так получилось. Поэтому, пожалуйста, не голосуйте за реальные соображения, потому что это не соответствует регулярному выражению = evil mem. Но давайте также не будем проголосовать за это слишком много. Это всего лишь побочный сигнал для этой темы.
DOMComment
может читать комментарии, поэтому нет причин использовать Regex для этого.
– Gordon
6 September 2010 в 10:48
DOM
использует libxml и libxml имеет отдельный модуль парсера HTML, который будет использоваться при загрузке HTML с помощью loadHTML()
, поэтому он может очень сильно загружать «реальный мир». (прочитанный сломанный) HTML.
– Gordon
6 September 2010 в 10:57
Существует много способов обработки HTML / XML DOM, о которых большинство уже упоминалось. Следовательно, я не буду пытаться их перечислить.
Я просто хочу добавить, что лично я предпочитаю использовать расширение DOM и почему:
И хотя я пропускаю возможность использования селекторов CSS для DOMDocument
, существует довольно простой и удобный способ добавления эта функция: подклассификация DOMDocument
и добавление JS-подобных методов querySelectorAll
и querySelector
в ваш подкласс.
Для разбора селекторов я рекомендую использовать очень минималистический компонент CssSelector из рамки Symfony , Этот компонент просто переводит селектора 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 Фабьеном Потенцером по его решению создать компонент CssSelector для Symfony и как используйте его.
phpQuery и QueryPath чрезвычайно похожи в репликации свободного API jQuery. Вот почему они - два из самых простых подходов к правильно анализируют HTML в PHP.
Примеры для QueryPath
В основном вы сначала создаете запрашиваемое дерево DOM из строки HTML:
$qp = qp("<html><body><h1>title</h1>..."); // or give filename or URL
Результирующий объект содержит полное древовидное представление документа HTML. Он может быть пройден с использованием методов DOM. Но общий подход заключается в использовании селекторов CSS, например, в jQuery:
$qp->find("div.classname")->children()->...;
foreach ($qp->find("p img") as $img) {
print qp($img)->attr("src");
}
. В основном вы хотите использовать простые #id
и .class
или DIV
селектор тэгов для ->find()
. Но вы также можете использовать операторы XPath , которые иногда бывают быстрее. Также типичные методы jQuery, такие как ->children()
и ->text()
и особенно ->attr()
, упрощают извлечение правильных фрагментов HTML. (И уже имеют свои SGML-объекты, декодированные.)
$qp->xpath("//div/p[1]"); // get first paragraph in a div
QueryPath также позволяет вводить новые теги в поток (->append
), а затем выводить и префикс обновленного документа (->writeHTML
). Он может не только анализировать искаженный HTML, но также различные диалекты XML (с пространствами имен) и даже извлекать данные из микроформатов HTML (XFN, vCard).
$qp->find("a[target=_blank]")->toggleClass("usability-blunder");
.
phpQuery или QueryPath?
Обычно QueryPath лучше подходит для манипулирования документами. В то время как phpQuery также реализует некоторые псевдо-AJAX-методы (только HTTP-запросы), более похожие на jQuery. Говорят, что phpQuery часто быстрее, чем QueryPath (из-за меньшего количества общих функций).
Для получения дополнительной информации о различиях см. это сравнение на машине обратного пути от tagbyte.org . (Оригинальный источник пропал без вести, так что вот ссылка интернет-архива. Да, вы все равно можете найти недостающие страницы, люди.)
И вот всеобъемлющее введение QueryPath .
Преимущества
->find("a img, a object, div a")
С помощью 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');
});
Вы можете попробовать использовать что-то вроде HTML Tidy , чтобы очистить любой «сломанный» HTML и преобразовать HTML в XHTML, который затем можно разобрать с помощью парсера XML.
QueryPath хорош, но будьте осторожны с состоянием отслеживания, если вы не понимаете, что это значит, это может означать, что вы тратите много времени на отладку, пытаясь выяснить, что произошло, почему код не работает.
Что это означает, что каждый вызов в результирующем наборе изменяет набор результатов в объекте, он не связан с цепочкой, как в jquery, где каждая ссылка является новым набором, у вас есть единый набор, который является результатом вашего запроса, и каждый вызов функции изменяет этот единственный набор.
, чтобы получить jquery-подобное поведение, вам нужно разветвиться до того, как вы выполните операцию фильтрации / модификации, означает, что он будет более точно отражать то, что происходит в jquery.
$results = qp("div p");
$forename = $results->find("input[name='forename']");
$results
теперь содержит результирующий набор для input[name='forename']
НЕ исходный запрос "div p"
, это сильно меня подтолкнуло, что Я обнаружил, что QueryPath отслеживает фильтры и находит и все, что изменяет ваши результаты и сохраняет их в объекте. вам нужно сделать это вместо
$forename = $results->branch()->find("input[name='forname']")
, тогда $results
не будет изменено, и вы можете повторно использовать результирующий набор снова и снова, возможно, кто-то, у кого гораздо больше знаний, может немного прояснить это, но это в основном похоже на то, что я нашел.
Просто используйте DOMDocument-> loadHTML () и выполняйте его. Алгоритм анализа XML в формате libxml довольно хорош и быстр, и, вопреки распространенному мнению, не задушивает искаженный HTML.
Один общий подход, о котором я не упоминал здесь, заключается в том, чтобы запустить HTML через Tidy , который может быть настроен на выдачу гарантированного действительного XHTML. Затем вы можете использовать любую старую библиотеку XML.
Но к вашей конкретной проблеме вы должны взглянуть на этот проект: http://fivefilters.org/content-only/ - это модифицированная версия алгоритма Readability , который предназначен для извлечения только текстового содержимого (а не верхних и нижних колонтитулов) со страницы.
Я создал библиотеку под названием 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;
Это звучит как хорошая задача описания технологии W3C XPath . Легко выразить такие запросы, как «вернуть все href
атрибуты в тегах img
, которые вложены в <foo><bar><baz> elements
». Не являясь баффом PHP, я не могу сказать вам, в какой форме XPath может быть доступен. Если вы можете вызвать внешнюю программу для обработки HTML-файла, вы сможете использовать версию командной строки XPath. Для быстрого ввода см. http://en.wikipedia.org/wiki/XPath .
Это, кстати, называется прокруткой экрана. Библиотека, которую я использовал для этого, - Простой HTML-парсер (/ g0).
Да, вы можете использовать simple_html_dom для этой цели. Однако я довольно много работал с simple_html_dom, особенно для веб-лома и обнаружил, что он слишком уязвим. Он выполняет основную работу, но я не буду рекомендовать ее в любом случае.
Я никогда не использовал завиток для этой цели, но то, что я узнал, заключается в том, что завиток может сделать работу намного эффективнее и намного более твердый.
Просьба проверить эту ссылку: выскабливание-сайты-с-завиток
Я написал анализатор XML общего назначения, который может легко обрабатывать файлы GB. Он основан на XMLReader, и он очень прост в использовании:
$source = new XmlExtractor("path/to/tag", "/path/to/file.xml");
foreach ($source as $tag) {
echo $tag->field1;
echo $tag->field2->subfield1;
}
Вот github repo: XmlExtractor
Структура Symfony имеет пакеты, которые могут анализировать HTML, и вы можете использовать стиль CSS для выбора DOMs вместо использования XPath .
XML_HTMLSax
довольно стабилен - даже если он больше не поддерживается. Другой вариант может заключаться в том, чтобы передать вам HTML через Html Tidy , а затем проанализировать его стандартными инструментами XML.