Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. PHP
Code

З екрану до столу: розбір HTML за допомогою бібліотеки Simple HTML DOM

by
Difficulty:IntermediateLength:MediumLanguages:

Ukrainian (українська мова) translation by Anton Bagaiev (you can also view the original English article)

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


Крок 1. Підготовка

Перше, що вам потрібно зробити, це завантажити копію бібліотеки simpleHTMLdom, що знаходиться у вільному доступі на sourceforge.

Для завантаження доступно декілька файлів, але вам потрібно завантажити лише файл simple_html_dom.php; все інше це приклади та документація.

Download from Sourceforge

Крок 2. Основи парсингу

Ця бібліотека дуже проста у використанні, але є деякі основи, що потрібно переглянути, перш ніж діяти.

Завантаження HTML

Можна створити початковий об'єкт або шляхом завантаження HTML з рядка, або з файлу. Файл можна завантажити з мережі за посиланням, або взяти з вашої локальної файлової системи.

Зверніть увагу: метод load_file() делегує свою роботу функції РНР file_get_contents(). Якщо у вашому файлі налаштувань php.ini немає запису "allow_url_fopen = true", ви не зможете відкрити віддалений файл таким чином. Проте, ви завжди можете використати бібліотеку CURL для завантаження віддалених сторінок, а потім прочитати їх за допомогою методу load().

Доступ до інформації

Transforming your HTML

Коли ви вже маєте DOM об'єкт, ви можете почати працювати з ним за допомогою find() для створення колекцій. Колекція це група об'єктів, які знайдені за допомогою селекторів, синтаксис яких дуже схожий на синтаксис селекторів у jQuery.

У цьому прикладі ми розберемо, як отримати доступ до інформації в другому параграфі, змінити його, і вивести результат.

Виклик методу find() з селектором у першому параметрі завжди повертає колекцію (масив) HTML-тегів. Вказавши число у другому параметрі, ви отримуєте енний дочірний елемент.

Рядки 2-4: Завантаження HTML із рядка, як описано раніше.

Рядок 7: Цей рядок знаходить всі теги <p> у вихідному HTML і повертає їх як масив. Перший параграф буде мати індекс 0, і відповідно буде проіндексовано наступні абзаци.

Рядок 10: Отримуємо доступ до 2-го пункту в нашій колекції параграфів (індекс 1) і змінюємо його атрибут innertext. Innertext представляє вміст між відкриваючими і закриваючими тегами, в той час як outertext представляє вміст, включаючи теги. Ми можемо замінити весь тег із його змістом за допомогою outertext.

Зараз ми додамо ще один рядок коду, щоб змінити клас другого параграфу.

У результаті виклику методу save() ми отримаємо такий HTML-код:

Інші селектори

Ось інші приклади селекторів. Якщо ви використовували jQuery, вони здадуться вам добре знайомими.

Набір параметрів у першому прикладі не зовсім інтуїтивний - всі селектори за замовчуванням повертають масив — навіть за використання селектору за ідентифікатором, якому за визначенням має відповідати лише один елемент. Однак, вказавши другий параметр, ми говоримо: "поверни тільки перший пункт цієї колекції".

Це означає, що значенням $single стане один елемент, а не масив, у який входить лише цей елемент.

Інші приклади говорять самі за себе.

Документація

Повну документацію бібліотеки ви можете знайти на сторінці документації проекту.

special properties

Крок 3. Реальний приклад

Щоб спробувати цю бібліотеку в дії, ми напишемо простий скрипт для збору контенту веб-сайту Nettuts, діставши перелік матеріалів, присутніх на сайті, у вигляді заголовку і опису... тільки для прикладу. Пам'ятайте, що парсинг це мудрована ділянка вебу і цього краще не робити без дозволу.

Screen Scraping Nettuts

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

Також ми оголосимо глобальний масив, щоб зробити збір всієї інформації в одному місці простішим. Перш ніж ми почнемо парсинг, давайте поглянемо, як огляд статті виглядає на Nettuts+.

Так виглядає відображення статті на сайті, разом із коментарями у коді. Чому коментарі це важливо? Бо синтаксичний аналізатор також враховує і їх.


Крок 4. Починаємо функцію парсингу

Починаючи з найпростішого, ми оголосимо нашу глобальну змінну, створимо новий об'єкт simple_html_dom, а потім завантажимо сторінку, яку ми хочемо розібрати. Пізніше ця функція буде викликатися рекурсивно, тож у першому параметрі вона буде приймати URL-адресу.


Крок 5. Знаходимо потрібну інформацію

Count The Children

Тут вся сіль функції getArticles(). Давайте подивимося уважніше, щоб дійсно зрозуміти, що відбувається.

Рядок 1: Створює масив елементів <div> з класом "preview". Тепер у змінній $items ми маємо колекцію статей.

Рядок 5: $post тепер вказує на один елемент <div> з класом "preview". Оглянувши вихідний HTML, ми можемо побачити, що третій дочірний елемент це <h1>, що містить назву статті. Візьмемо його і запишемо у $articles[індекс][0].

Пам'ятайте, що треба починати рахувати з нуля та не забувати про коментарі, визначаючи відповідний індекс дочірнього вузла.

Рядок 6: Шостий дочірний елемент у $post це <div class="text">. Нам потрібен текст опису всередині тегу, тож візьмемо перший дочірний елемент від outertext - це буде включати тег абзацу. Один запис у масиві зібраних статей тепер має такий вигляд:


Крок 6. Пагінація

Спочатку визначимо, як знайти нашу наступну сторінку. На сайті Nettuts+ це легко зрозуміти з URL-адреси, але ми зробимо вигляд, що не знаємо цього і отримаємо адресу наступної сторінки за допомогою парсингу.

Find the next page to parse

Якщо ми подивимося у HTML, то побачимо наступне:

Якщо є наступна сторінка (а так буде не кожного разу), ми знайдемо якір з класом "nextpostslink". Тепер використаємо цю інформацію.

В першому рядку ми бачимо, чи є якір з класом "nextpostslink". Зверніть увагу на другий параметр методу find(). Ми визначаємо, що хочемо взяти лише перший елемент колекції (з індексом 0). Так змінна $next буде зберігати тільки один елемент, а не масив елементів.

Далі ми покладемо у змінну $URL значення з атрибуту "href", що містить посилання. Це важливо, бо зараз ми будемо знищувати HTML-об'єкт. З огляду на циклічні виклики, що призводять до витіку пам'яті у PHP5, поточний об'єкт simple_html_dom повиннен бути очищений і знищений перед тим, як буде створений наступний. Це допоможе вам не з'їдати всю доступну пам'ять.

Нарешті, ми можемо викликати getArticles() з URL-адресою наступної сторінки. Ця рекурсія завершиться, коли не залишиться сторінок для парсингу.


Крок 7. Відображаємо результат

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

Final Output

Далі ми вставимо невеликий шмат PHP-коду на сторінці, щоб вивести попередньо зібрану інформацію.

Остаточним результатом буде сторінка HTML, що містить список всіх статей, починаючи зі сторінки, що буде зазначена у першому виклику функції getArticles().


Крок 8. Висновок

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

На такому сайті, як Nettuts, за існуючих 78 сторінок, це буде працювати більше за одну хвилину.

Цей навчальний матеріал має допомогти вам ознайомитись із HTML-парсингом. Є й інші способи роботи з DOM, включаючи вбудований у РНР, що дозволяє працювати з потужними xpath-селекторами для знаходження елементів. Але я вважаю, що завдяки простоті використання ця бібліотека є однією з кращих для швидкого старту. На завершення я хочу знову звернути увагу, що треба завжди пам'ятати про отримання дозволу, перш ніж парсити сайти — це дуже важливо. Дякую за увагу!

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.