Як ви аналізуєте та обробляєте HTML / XML в PHP?


Відповіді:


1897

Рідні розширення XML

Я вважаю за краще використовувати одне з власних розширень XML, оскільки вони поставляються в комплекті з PHP, як правило, швидше, ніж усі сторонні розширення та надають мені весь контроль, який мені потрібен над розміткою.

DOM

Розширення DOM дозволяє працювати з документами XML за допомогою API DOM з PHP 5. Це реалізація документа W3C Document Object Model Core Level 3, нейтральний для платформи та мови інтерфейс, що дозволяє програмам та сценаріям динамічно отримувати доступ та оновлювати зміст, структура та стиль документів.

DOM здатний аналізувати та змінювати HTML-код реального світу (зламаного), і він може робити XPath-запити . Він заснований на libxml .

Для отримання продуктивності з DOM потрібен певний час, але цей час вартий того, щоб це IMO. Оскільки DOM - це мовно-агностичний інтерфейс, ви знайдете реалізацію на багатьох мовах, тому якщо вам потрібно змінити мову програмування, швидше за все, ви вже будете знати, як використовувати API DOM цієї мови тоді.

Основний приклад використання можна знайти в захопленні атрибута href елемента A, а загальний концептуальний огляд можна знайти на DOMDocument в php

Як використовувати розширення DOM широко висвітлено в StackOverflow , тож якщо ви вирішите його використовувати, ви можете бути впевнені, що більшість проблем, які ви стикаєтеся , можна вирішити шляхом пошуку / перегляду переповнення стека.

XMLReader

Розширення XMLReader - це синтаксичний аналізатор XML. Зчитувач виступає як курсор, який рухається вперед по потоку документів і зупиняється на кожному вузлі на шляху.

XMLReader, як і DOM, заснований на libxml. Я не знаю, як запустити модуль HTML-парсера, тому шанси використання XMLReader для розбору зламаного HTML можуть бути менш надійними, ніж використання DOM, де ви можете чітко сказати йому використовувати модуль HTML-парсера libxml.

Основний приклад використання можна знайти при отриманні всіх значень з h1 тегів за допомогою php

XML-аналізатор

Це розширення дозволяє створювати XML-аналізатори та потім визначати обробники для різних подій XML. Кожен аналізатор XML також має кілька параметрів, які ви можете налаштувати.

Бібліотека XML Parser також базується на libxml та реалізує XML- розбірник стилів XML у стилі SAX . Це може бути кращим вибором для управління пам'яттю, ніж DOM або SimpleXML, але працювати буде складніше, ніж аналізатор тяжіння, реалізований XMLReader.

SimpleXml

Розширення SimpleXML забезпечує дуже простий і легко зручний набір інструментів для перетворення XML в об'єкт, який можна обробити звичайними селекторами властивостей та ітераторами масиву.

SimpleXML - це варіант, коли ви знаєте, що HTML є дійсним XHTML. Якщо вам потрібно розібрати зламаний HTML, навіть не розглядайте SimpleXml, оскільки він задихнеться.

Основний приклад використання можна знайти в Простій програмі для значень вузла та вузла CRUD у файлі xml, і в Посібнику з PHP є багато додаткових прикладів .


Сторонні бібліотеки (на основі libxml)

Якщо ви віддаєте перевагу використовувати сторонній lib, я б запропонував використовувати lib, який фактично використовує DOM / libxml під ним замість розбору рядків.

FluentDom - Repo

FluentDOM забезпечує jQuery-подібний вільний XML-інтерфейс для DOMDocument в PHP. Селектори записуються в XPath або CSS (використовуючи перетворювач CSS в XPath). Поточні версії розширюють DOM, що реалізує стандартні інтерфейси та додають функції з DOM Living Standard. FluentDOM може завантажувати такі формати, як JSON, CSV, JsonML, RabbitFish та інші. Можна встановити через Composer.

HtmlPageDom

Wa72 \ HtmlPageDom` - це бібліотека PHP для зручного маніпулювання документами HTML, використовуючи для цього потрібний DomCrawler з компонентів Symfony2 для переходу до дерева DOM та розширення, додаючи методи маніпулювання деревом DOM з HTML-документів.

phpQuery (не оновлюється роками)

phpQuery - це серверний, керований селектором CSS3, API, орієнтований на модель об'єкта документа (DOM), заснований на бібліотеці jQuery JavaScript, написаній на PHP5, та забезпечує додатковий інтерфейс командного рядка (CLI).

Також дивіться: https://github.com/electrolinux/phpquery

Zend_Dom

Zend_Dom надає інструменти для роботи з документами та структурами DOM. В даний час ми пропонуємо Zend_Dom_Query, який забезпечує уніфікований інтерфейс для запиту документів DOM з використанням як XPath, так і CSS-селекторів.

QueryPath

QueryPath - це бібліотека PHP для управління XML та HTML. Він призначений для роботи не тільки з локальними файлами, але і з веб-службами та ресурсами бази даних. Він реалізує більшу частину інтерфейсу jQuery (включаючи селектори стилів CSS), але він сильно налаштований для використання на сервері. Можна встановити через Composer.

fDOMдокумент

fDOMDocument розширює стандартний DOM для використання виключень при будь-яких випадках помилок замість попереджень або повідомлень PHP. Вони також додають різні спеціальні методи та ярлики для зручності та спрощення використання DOM.

шабля / хмл

saber / xml - це бібліотека, яка обгортає та розширює класи XMLReader та XMLWriter, щоб створити просту систему картографування "xml для об'єкта / масиву" та шаблон дизайну. Написання та читання XML є однопрохідним і тому може бути швидким і вимагати малої пам’яті для великих xml-файлів.

FluidXML

FluidXML - це бібліотека PHP для маніпулювання XML стислим та вільним API. Він використовує XPath та схему вільного програмування, щоб бути веселим та ефективним.


Сторонні (не на основі libxml)

Перевага на основі DOM / libxml полягає в тому, що ви отримуєте хороші показники роботи поза коробкою, оскільки ви базуєтесь на нативному розширенні. Однак не всі сторонні лізери йдуть цим шляхом. Деякі з них перераховані нижче

PHP Простий HTML-аналізатор DOM

  • Розбір HTML DOM, написаний на PHP5 +, дозволяє вам маніпулювати HTML дуже простим способом!
  • Потрібна PHP 5+.
  • Підтримує недійсний HTML.
  • Знайдіть теги на HTML-сторінці за допомогою селекторів так само, як jQuery.
  • Витягнути вміст з HTML в одному рядку.

Я зазвичай не рекомендую цей аналізатор. Кодова база жахлива, і сам аналізатор досить повільний і голодний. Не всі селектори jQuery (наприклад, дочірні селектори ) можливі. Будь-яка з бібліотек на основі libxml повинна легко перевершити це.

PHP Html Parser

PHPHtmlParser - це простий, гнучкий, html-аналізатор, який дозволяє вибирати теги за допомогою будь-якого селектора css, наприклад jQuery. Мета - допомогти у розробці інструментів, які потребують швидкого та простого способу сканування HTML, незалежно від того, дійсний він чи ні! Цей проект оригінально підтримувався sunra / php-simple-html-dom-parser, але, здається, підтримка припинилась, тому цей проект є моєю адаптацією його попередньої роботи.

Знову ж таки, я б не рекомендував цей аналізатор. Він досить повільний з високим рівнем використання процесора. Немає також функції очищення пам'яті створених об'єктів DOM. Ці проблеми масштабуються особливо з вкладеними петлями. Сама документація є неточною та неправильно написаною, без відповідей на виправлення з 14 квітня 16 квітня.

Ганон

  • Універсальний токенізатор та парсер HTML / XML / RSS DOM Parser
    • Можливість маніпулювати елементами та їх атрибутами
    • Підтримує недійсні HTML та UTF8
  • Може виконувати розширені запити, схожі на CSS3, на елементи (наприклад, jQuery - підтримуються простори імен)
  • HTML-красуня (наприклад, HTML Tidy)
    • Мінімізуйте CSS та Javascript
    • Сортувати атрибути, змінити регістр символів, правильний відступ тощо.
  • Розширюваний
    • Розбір документів за допомогою зворотних дзвінків на основі поточного символу / маркера
    • Операції розділені на більш дрібні функції для легкого переосмислення
  • Швидко і легко

Ніколи не використовував. Не можу сказати, чи це добре.


HTML 5

Ви можете використовувати вищезазначене для розбору HTML5, але можуть бути химерності завдяки розмітці HTML5. Тож для HTML5 ви хочете розглянути можливість використання виділеного аналізатора, наприклад

html5lib

Реалізації Python та PHP HTML-аналізатора на основі специфікації WHATWG HTML5 для максимальної сумісності з основними веб-браузерами настільних ПК.

Ми можемо побачити більше виділених аналізаторів, коли HTML5 буде доопрацьовано. Існує також допис для блогу під назвою W3 під назвою How-To для розбору html 5, який варто перевірити.


Веб-сервіси

Якщо ви не любите програмувати PHP, ви також можете користуватися веб-сервісами. Загалом, я знайшов дуже мало корисних для них, але це лише я та мої випадки використання.

ScraperWiki .

Зовнішній інтерфейс ScraperWiki дозволяє витягувати дані у потрібній формі для використання в Інтернеті або у власних програмах. Ви також можете отримати інформацію про стан будь-якого скрепера.


Регулярні вирази

Останнє і найменш рекомендоване , ви можете витягувати дані з HTML за допомогою регулярних виразів . Взагалі використання регулярних виразів на HTML не рекомендується.

Більшість фрагментів, які ви знайдете в Інтернеті, щоб відповідати розмітці, є крихкими. У більшості випадків вони працюють лише для дуже конкретного фрагмента HTML. Невеликі зміни розмітки, як-от додавання пробілу десь або додавання чи зміна атрибутів у тегу, можуть призвести до відмови RegEx, якщо він не написаний належним чином. Ви повинні знати, чим займаєтесь, перш ніж використовувати RegEx на HTML.

HTML-аналізатори вже знають синтаксичні правила HTML. Регулярні вирази повинні викладатися для кожного нового RegEx, який ви пишете. RegEx в деяких випадках добре, але це дійсно залежить від вашого використання.

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

Також див. Розбір Html The Cthulhu Way


Книги

Якщо ви хочете витратити трохи грошей, погляньте

Я не пов'язаний з архітектором PHP або авторами.


10
@Naveed, що залежить від ваших потреб. У мене немає потреби в CSS Selector-запитах, саме тому я використовую DOM виключно з XPath. phpQuery має на меті бути портом jQuery. Zend_Dom легкий. Вам дійсно доведеться перевірити їх, щоб побачити, який із них вам найбільше подобається.
Гордон

2
@ Ms2ger Здебільшого, але не повністю. Як вже було зазначено вище, ви можете використовувати аналізатори на основі libxml, але є особливі випадки, коли вони задушаться. Якщо вам потрібна максимальна сумісність, вам краще використовувати спеціальний аналізатор. Я вважаю за краще зберігати відмінність.
Гордон

9
Ваша думка щодо використання PHP Simple HTML DOM Parser здається суперечливою.
Пета

3
Станом на 29 березня 2012 року, DOM не підтримує html5, XMLReader не підтримує HTML, а остання фіксація html5lib для PHP - на вересень 2009 року. Що використовувати для розбору HTML5, HTML4 та XHTML?
Шиплу Мокаддім

4
@Nasha Я навмисно виключив сумнозвісного ренту Zalgo зі списку вище, оскільки це не надто корисно, і це призвело до досить вантажного культу з моменту написання. Люди були забиті за допомогою цієї ланки, незалежно від того, наскільки правильним би був регулярний вираз. Для більш збалансованого думки, будь ласка , см посилання я зробив включити замість цього і пройти через коментарі в stackoverflow.com/questions/4245008 / ...
Gordon

322

Спробуйте простий парсер HTML DOM Parser

  • Розбір HTML DOM, написаний на PHP 5+, що дозволяє вам маніпулювати HTML дуже простим способом!
  • Потрібна PHP 5+.
  • Підтримує недійсний HTML.
  • Знайдіть теги на HTML-сторінці за допомогою селекторів так само, як jQuery.
  • Витягнути вміст з HTML в одному рядку.
  • Завантажити


Приклади:

Як отримати елементи HTML:

// Create DOM from URL or file
$html = file_get_html('http://www.example.com/');

// Find all images
foreach($html->find('img') as $element)
       echo $element->src . '<br>';

// Find all links
foreach($html->find('a') as $element)
       echo $element->href . '<br>';


Як змінити елементи HTML:

// Create DOM from string
$html = str_get_html('<div id="hello">Hello</div><div id="world">World</div>');

$html->find('div', 1)->class = 'bar';

$html->find('div[id=hello]', 0)->innertext = 'foo';

echo $html;


Вилучення вмісту з HTML:

// Dump contents (without tags) from HTML
echo file_get_html('http://www.google.com/')->plaintext;


Вискоблювання Slashdot:

// Create DOM from URL
$html = file_get_html('http://slashdot.org/');

// Find all article blocks
foreach($html->find('div.article') as $article) {
    $item['title']     = $article->find('div.title', 0)->plaintext;
    $item['intro']    = $article->find('div.intro', 0)->plaintext;
    $item['details'] = $article->find('div.details', 0)->plaintext;
    $articles[] = $item;
}

print_r($articles);

8
Ну, по-перше, є речі, які мені потрібно підготувати, наприклад, поганий DOM, невірний код, також js, що аналізує ДНСБЛ двигун; це також буде використано для пошуку шкідливих сайтів / контенту, також, як я створив свій сайт навколо рамки i побудувавши його потрібно, щоб він був чистим, читабельним і добре структурованим. SimpleDim чудовий, але код трохи безладний
RobertPitt

9
@Robert Ви також можете перевірити htmlpurifier.org на предмет безпеки.
Гордон

3
У нього є один дійсний пункт: простийHTMLDOM важко розширити, якщо тільки ви не використовуєте шаблон декоратора, який я вважаю загрозливим. Я виявив, що я здригнувся, лише вносячи зміни в основні класи.
Ерік

1
Що я зробив, запустив html через охайність, перш ніж надсилати його в SimpleDOM.
MB34

1
Я зараз це використовую, запускаю його як частину проекту для обробки декількох сотень URL-адрес. Це стає дуже повільним і регулярні тайм-аути зберігаються. Це чудовий сценарій для початківців і простий у навчанні інтуїтивно зрозумілий, але занадто базовий для більш просунутих проектів.
luke_mclachlan

236

Просто використовуйте DOMDocument-> loadHTML () і виконайте це. Алгоритм розбору HTML libxml є досить хорошим і швидким, і всупереч поширеній думці, не задихається неправильним HTML.


19
Правда. Він працює з вбудованими класами XPath та XSLTProcessor PHP, які чудово підходять для вилучення вмісту.
Корнель

8
Для дійсно керованого HTML, ви завжди можете запустити його через htmltidy, перш ніж передавати його DOM. Щоразу, коли мені потрібно скребти дані з HTML, я завжди використовую DOM або принаймні simplexml.
Френк Фермер

9
Інша річ із завантаженням неправильно сформованого HTML i, що, можливо, було б розумно зателефонувати libxml_use_internal_errors (правда), щоб запобігти попередженням, які припинять розбір.
Хаскі

6
Я використовував DOMDocument для розбору близько 1000 html-джерел (різними мовами, закодованими різними символами) без жодних проблем. Ви можете зіткнутися з проблемами кодування з цим, але вони не є непереборними. Вам потрібно знати 3 речі: 1) loadHTML використовує схему метатегів для визначення кодування 2) # 2 може призвести до неправильного виявлення кодування, якщо вміст html не містить цієї інформації 3) погані символи UTF-8 можуть відключити парсер. У таких випадках використовуйте комбінацію mb_detect_encoding () та кодування / конвертування / відключення / усунення поганого коду символів UTF-8 Simplepie RSS RSS Parser для обходу.
Нуль

1
DOM насправді підтримує XPath, погляньте на DOMXPath .
Райан МакКью

147

Чому не слід і коли слід використовувати регулярні вирази?

По-перше, поширена помилка: Regexps не для " розбору " HTML. Регекси можуть, однак, " витягувати " дані. Видобуток - це те, для чого вони зроблені. Основним недоліком вилучення HTML-регексу над належними наборами інструментів SGML або базовими XML-аналізаторами є їх синтаксичні зусилля та різна надійність.

Розглянемо, як зробити дещо надійний регекс для вилучення HTML:

<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");

Однак є конкретні випадки використання, коли вони можуть допомогти.

  • Багато фронталів обходу DOM не виявляють коментарів HTML <!--, які, однак, іноді є більш корисними якорями для вилучення. Зокрема, варіації псевдо HTML<$var> або залишки SGML легко приручити за допомогою регулярних виразів.
  • Часто регулярні вирази можуть зберегти після обробки. Однак HTML-субстанції часто потребують ручного догляду.
  • І нарешті, для таких надзвичайно простих завдань, як вилучення <img src = urls, вони насправді є імовірним інструментом. Перевага швидкості перед парсерами SGML / XML здебільшого просто грає для цих самих основних процедур вилучення.

Іноді навіть доцільно попередньо витягти фрагмент HTML, використовуючи регулярні вирази, /<!--CONTENT-->(.+?)<!--END-->/а решту обробити за допомогою більш простого фронталу HTML синтаксичного аналізу.

Примітка. Насправді у мене є ця програма , де я використовую XML-синтаксичний аналіз та регулярні вирази. Лише минулого тижня розбір PyQuery зламався, і регулярний вираз продовжував працювати. Так дивно, і я не можу сам це пояснити. Але так сталося.
Тож, будь ласка, не голосуйте з реальних міркувань лише тому, що це не відповідає регексу = злому мему. Але давайте також не будемо занадто голосувати за це. Це просто сторонне позначення цієї теми.


20
DOMCommentможе читати коментарі, тому немає причин використовувати Regex для цього.
Гордон

4
Ні набори інструментів SGML, ні парсери XML не підходять для аналізу HTML реального світу. Для цього підходить лише виділений HTML-аналізатор.
Alohci

12
@Alohci DOMвикористовує libxml, а libxml має окремий модуль HTML-аналізатора, який буде використовуватися при завантаженні HTML, loadHTML()щоб він міг значно завантажувати "реальний світ" (читати ламаний) HTML.
Гордон

6
Ну, лише коментар щодо вашої точки зору "реального розгляду". Звичайно, Є корисні ситуації для Regex при аналізі HTML. Також є корисні ситуації для використання GOTO. І існують корисні ситуації для змінних змінних. Тому жодна конкретна реалізація не є остаточно кодовою гниллю для її використання. Але це ДУЖЕ сильний попереджувальний знак. І середній розробник, ймовірно, не буде достатньо нюансований, щоб визначити різницю. Отже, як правило, Regex GOTO і Variable-Variables - це все зло. Існує недобре використання, але це винятки (і рідкісні в цьому) ... (ІМХО)
ircmaxell

11
@mario: Насправді HTML можна «правильно» проаналізувати за допомогою регулярних виразів, хоча зазвичай потрібно декілька з них, щоб виконати справедливу роботу. Це просто королівський біль у загальному випадку. У конкретних випадках із чітко вираженим вкладом, він перетворюється на тривіальне. Ось такі випадки, коли люди повинні використовувати регулярні вирази. Великі старі голодні важкі парсери - це справді те, що потрібно для загальних випадків, хоча випадковому користувачеві не завжди зрозуміло, де провести цю межу. Будь-який код простіший і легший, виграє.
tchrist

131

phpQuery і QueryPath дуже схожі на тиражування вільно JQuery API. Ось чому це два найпростіші підходи до правильного розбору 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")
  • Належне скасування даних (порівняно зі звичайним зіставленням виразів)

88

Простий HTML DOM - це чудовий аналізатор з відкритим кодом:

simplehtmldom.sourceforge

Він обробляє елементи DOM об'єктно-орієнтованим способом, і нова ітерація має багато покриття для невідповідного коду. Існує також кілька чудових функцій, як ви бачите в JavaScript, наприклад, функція "знайти", яка повертає всі екземпляри елементів цього імені тегу.

Я використовував це в ряді інструментів, тестуючи його на багатьох різних веб-сторінках, і я думаю, що це чудово працює.


61

Один загальний підхід, якого я не бачив тут, - це запускати HTML через Tidy , який можна встановити, щоб виплюнути гарантовано дійсний XHTML. Тоді ви можете використовувати будь-яку стару бібліотеку XML на ній.

Але до вашої конкретної проблеми слід поглянути на цей проект: http://fivefilters.org/content-only/ - це модифікована версія алгоритму читабельності , яка призначена для вилучення лише текстового вмісту (а не заголовків) і колонтитули) зі сторінки.


56

За 1а та 2: Я би проголосував за новий клас Symboly Componet DOMCrawler ( DomCrawler ). Цей клас дозволяє запити, подібні до CSS Selectors. Погляньте на цю презентацію на приклади реального світу: новини-про-символу2-світу .

Компонент розроблений для самостійної роботи і може використовуватися без Symfony.

Єдиний недолік - це те, що він буде працювати лише з PHP 5.3 або новішою версією.


jquery-подібні CSS-запити добре сказані, оскільки в документації на w3c відсутні деякі речі, але вони є додатковими функціями в jquery.
Микола Петканський

53

Це , до речі, називають екрануванням екрана . Бібліотека, яку я використав для цього, - простий HTML Dom Parser .


8
Не зовсім суворо ( en.wikipedia.org/wiki/Screen_scraping#Screen_scraping ). Підказка в «екрані»; у описуваному випадку екран не задіяний. Хоча, правда, цей термін зазнав дуже багато останніх зловживань.
Боббі Джек

4
Я не знімаю екран, вміст, який буде проаналізований, буде дозволений постачальником вмісту за моєю угодою.
РобертПітт

41

Раніше ми створили досить багато сканерів для наших потреб. Зрештою, зазвичай прості регулярні вирази роблять річ найкраще. Хоча бібліотеки, перелічені вище, корисні з тієї причини, яку вони створюють, якщо ви знаєте, що шукаєте, регулярні вирази - це більш безпечний шлях, оскільки ви можете обробляти також недійсні структури HTML / XHTML , що не вдасться при завантаженні через більшість парсерів.



36

Це звучить як хороший опис завдань технології W3C XPath . Висловити запити на кшталт "повернути всі hrefатрибути в imgтеги, які вкладені <foo><bar><baz> elements" , легко . Не будучи PHP бафом, я не можу сказати вам, у якій формі XPath може бути доступний. Якщо ви можете викликати зовнішню програму для обробки HTML-файлу, ви повинні мати можливість використовувати версію XPath командного рядка. Для швидкого вступу дивіться сторінку http://en.wikipedia.org/wiki/XPath .


29

Сторонні альтернативи SimpleHtmlDom , що використання DOM замість обробка рядків: phpQuery , Zend_Dom , QueryPath і FluentDom .


3
Якщо ви вже скопіювати мої коментарі, по крайней мере , зв'язати їх належним чином;) Це має бути: Пропоновані альтернативи сторонніми SimpleHtmlDom , що на насправді використовувати DOM замість Струнний Синтаксичний: phpQuery , Zend_Dom , QueryPath і FluentDom .
Гордон

1
Хороші відповіді - чудове джерело. stackoverflow.com/questions/3606792 / ...
danidacar

24

Так, ви можете використовувати simple_html_dom для своїх цілей. Однак я досить багато працював із simple_html_dom, особливо для розробки веб-сайтів і виявив, що це занадто вразливий. Це виконує основну роботу, але я її все одно не рекомендую.

Я ніколи не використовував curl з ціллю, але те, що я дізнався, це те, що curl може зробити цю роботу набагато ефективніше і набагато більш міцною.

Будь ласка, ознайомтеся з цим посиланням: scraping-sites-with-curl


2
curl може отримати файл, але він не розбере HTML для вас. Це важка частина.
cHao

23

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не буде змінено, і ви можете повторно використовувати набір результатів знову і знову, можливо, хтось, хто має набагато більше знань, може це трохи очистити, але це в основному так, як це я знайшов.


20

Розширений Html Dom - це проста заміна HTML DOM, яка пропонує той самий інтерфейс, але на основі DOM, що означає, що жодна з пов'язаних проблем із пам'яттю не виникає.

Він також має повну підтримку CSS, включаючи розширення jQuery .


Я отримав хороші результати від Advanced Html Dom, і, думаю, він повинен бути у списку у прийнятій відповіді. Хоча важливо знати, хоча для тих, хто покладається на його "Мета цього проекту - це заміна, що базується на DOM, для простої html-бібліотеки дому PHP ... Якщо ви використовуєте файл / str_get_html, то вам не потрібно щось змінити ». archive.is/QtSuj#selection-933.34-933.100 полягає в тому, що вам, можливо, знадобиться внести зміни у свій код, щоб уникнути деяких несумісностей. Я зазначив чотири відомих мені у випуску про github проекту. github.com/monkeysuffrage/advanced_html_dom/isissue
ChrisJJ

Працювали! Дякую
Файсал Шані

18

Для HTML5 літ html5 відмовився вже багато років. Єдина бібліотека HTML5, яку я можу знайти з останніми записами оновлень та обслуговування, - це html5-php, який щойно було доведено до бета-версії 1.0 трохи більше тижня тому.


17

Я написав аналізатор 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


17

Я створив бібліотеку під назвою PHPPowertools / DOM-Query , яка дозволяє сканувати документи HTML5 та XML так само, як і у jQuery.

Під капотом він використовує symfony / DomCrawler для перетворення селекторів CSS в селектори XPath . Він завжди використовує той самий DomDocument, навіть коли передає один об'єкт іншому, щоб забезпечити гідну продуктивність.


Приклад використання:

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>');

[...]

Підтримувані методи:


  1. Перейменований на "вибір" з очевидних причин
  2. Перейменований на "void", оскільки "порожній" - це зарезервоване слово в PHP

ПРИМІТКА :

Бібліотека також включає власний автозавантажувач нульової конфігурації для сумісних з бібліотеками PSR-0. Приклад, що входить, повинен працювати з вікна без додаткової конфігурації. Як варіант, ви можете використовувати його з композитором.


Схоже, це правильний інструмент для роботи, але не завантажується для мене в PHP 5.6.23 в Worpress. Будь-які додаткові вказівки щодо його правильного включення ?. Включено його з: define ("BASE_PATH", ім'я dirname ( FILE )); визначити ("LIBRARY_PATH", BASE_PATH. DIRECTORY_SEPARATOR. 'lib / vendor'); потрібно LIBRARY_PATH DIRECTORY_SEPARATOR 'Loader.php'; Loader :: init (масив (LIBRARY_PATH, USER_PATH)); in function.php
lithiumlab

15

Ви можете спробувати використати щось на кшталт HTML Tidy, щоб очистити будь-який "зламаний" HTML і перетворити HTML в XHTML, який ви зможете потім проаналізувати за допомогою аналізатора XML.


15

Ще один варіант, який ви можете спробувати, це QueryPath . Він натхненний jQuery, але на сервері в PHP і використовується в Drupal .


12

XML_HTMLSaxдосить стабільний - навіть якщо він більше не підтримується. Іншим варіантом може бути передавання HTML через Html Tidy, а потім його розбір зі стандартними інструментами XML.


11

Symfony рамки мають пучки , які можна розібрати на HTML, і ви можете використовувати стиль CSS для вибору Домс замість використання XPath .


11

Існує багато способів обробки HTML / XML DOM, про які більшість вже згадувалося. Отже, я не буду робити жодних спроб перерахувати їх самі.

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

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

І хоча мені не вистачає можливості використовувати селектори CSS для DOMDocument, є досить простий і зручний спосіб додати цю функцію: підкласифікація DOMDocumentта додавання JS-подібних querySelectorAllтаquerySelector методи підкласу.

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

Потім ви можете використовувати цей (ще дуже низький рівень) підклас як основу для класів більш високого рівня, призначених наприклад. проаналізуйте дуже специфічні типи XML або додайте більше поведінки, подібної jQuery.

Код нижче виходить з моєї бібліотеки запитів DOM і використовує описану нами техніку.

Для розбору 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 та способи його використання.


9

За допомогою FluidXML ви можете запитувати та повторювати XML за допомогою XPath та CSS Selectors .

$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

JSON і масив з XML у трьох рядках:

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

Та да!


7

Є кілька причин не розбирати 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

Я створив бібліотеку під назвою 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

Якщо ви знайомі з селектором 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 або відсутню цитату в атрибутах тегів.


0

Найкращий метод для розбору 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;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.