Парсинг контенту

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

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

Найчастіше доводиться мати справу з даними у форматі XML та HTML (XHTML). Матеріали, у більшій мірі, статті стосуються формату HTML.

Принципової різниці на чому писати парсер - не існує. Практично усі алгоритмічні мови загального призначення для цього придатні. Спеціалізовані, такі як 1С, JS чи VBA, теж для цього придатні. У своїй практиці я використовував 1С та PHP.

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

Нижче буде приведений поетапний опис створення парсера.

Для початку, для того, щоб не тратити час надаремно, перевірте, чи необхідні вам дані вдасться отримати без використання скриптів та флешу. Для цього необхідно, на деякий час, вимкнути їх підтримку в бравзері. Для спрощення цієї задачі я рекомендую використовувати плагін Mozilla Firefox "NoScript". Якщо необхідні дані ви не побачите ні у нормальному режимі, ні у початковому коді сторінки, - вам навряд вдасться отримати необхідний вам контент. Отримання даних, сформованих скриптами, що виконуються на стороні клієнта - завдання не просте і потребує відповідних навиків, значних системних ресурсів, додаткового спеціалізованого ПЗ та затрат часу розробника. Приховування даних за скриптами - це один з способів захистити їх від парсингу.

Наступне, що необхідно зробити - аналіз структури даних та визначити можливі її варіанти. Це - основний і найважчий етап. Без базового знання HTML тут не обійтися. На цьому етапі, базуючись на аналіз тегів, необхідно буде визначити селектори для потрібних нам блоків та елементів. Для цього необхідно переглянути початковий код сторінки. Цю можливість надають практично усі бавзери. Але, набагато зручніше є використання спеціалізованих інструментів: від текстових редакторів, що розпізнають теги і до плагінів барвзерів. Я використовую вбудовану в бравзер Mozilla Firefox функцію, що надає можливість аналізу HTML-сторінки. Для активації цієї функції цього необхідно за допомогою контекстного меню (клік правою кнопкою миші) на елементі, що представляє для нас інтерес та вибрати пункт "Дослідити елемент". У результаті цієї дії, у нижній частині вікна бравзера появиться блок з активною закладкою "Ревізор", у вікні якого буде частина HTML-коду з спозиційованим на вибраному раніше елементі виділенням. HTML-код відобразиться з відповідними відступами від лівого краю, що будуть виділяти блочні та рядкові елементи. На підставі проведеного аналізу, необхідно визначити селектори потрібних нам елементів. Найчастіше потрібна нам інформація обрамлена тегами , рідше чи .

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

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

На цьому етапі основна частина підготовчої роботи виконана. Можна приступати до реалізації програмного коду.

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

Ось приклади на PHP:

Отримання даних через файловий потік (з обробкою помилки)

$options = array(
'http'=>array(
'method'=>"GET",
'timeout' => MAX_CONTENT_TIMEOUT
)
);
$context = stream_context_create($options);
$contents = file_get_contents($url, false, $context);
if(!$contents)
throw new Exception($url.': Не вдалося отримати контент');

Отримання даних через за допомогою cURL (з обробкою помилки)

$ch = curl_init($url);

// Параметры курла
curl_setopt($ch, CURLOPT_USERAGENT, 'IE20');
curl_setopt($ch, CURLOPT_HEADER, 0);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, '1'); // повертати значення, а не виводити повідомлення

// Получаем html
$contents = curl_exec($ch);

// Отключаемся
curl_close($ch);

if(!$contents)
throw new Exception($url.': Не вдалося отримати контент');

Змінна $url містить стрічку з URL(URI) потрібної сторінки. У результаті виконання коду ми отримаємо вхідні дані (сторінку) у змінній $contents.

Далі, якщо у цьому є потреба, необхідно змінити кодування завантажених даних.
Приклад (PHP):

mb_convert_encoding($contents, 'UTF-8', 'Windows-1251');

Тепер ми маємо у змінній вхідні дані і можемо приступити безпосередньо до парсингу. Можна написати свій аналізатор тегів, але слід мати на увазі, що це дуже великий об'єм роботи. Необхідність написання такого аналізатора може виникнути при використанні нестандартних форматів чи невалідності HTML-коду. Цей складний випадок я не буду розглядати у цій статті. Якщо ж ми маємо справу з валідним HTML, суттєво спрости вирішення завдання може готовий клас, що може працювати з HTML через DOM (Document Object Model) - об'єктну модель документа. Використовуючи таку модель, можна досить просто отримувати потрібні нам блоки та елементи, працюючи з документом як з деревом (графом). Якщо ми використовуємо для реалізації коду парсера PHP, є два найпростіших шляхи: використати стандартний клас DOMDocument, який призначений для роботи з HTML/XML, чи сторонню бібліотеку PHP Simple HTML DOM Parser.

Приклад використання DOMDocument (PHP)

$dom = new DOMDocument();

$dom->loadHTML($contents);
$dom->preserveWhiteSpace = false;
$article = $dom->getElementsByTagName("article");
$article_html = $dom->saveHTML($article);

У результаті роботи даного фрагменту коду, змінна $article_html буде містити вміст першого блоку, виділеного тегом

Приклад використання PHP Simple HTML DOM Parser (PHP)

$simple_html = str_get_html($contents);

$article = $simple_html->find("article",0);
if(!isset($article))
throw new Exception('Невідомий формат новини!');

$article_html = trim($article->innertext)

У результаті роботи даного фрагменту коду, змінна $article_html буде містити вміст першого (номер 0) блоку, виділеного тегом

Бібліотека PHP Simple HTML DOM Parser вигідно відрізняється від класу DOMDocument можливістю уточнення вибору конкретного елементу, зберігаючи при цьому можливість послідовного перебору вибраних елементів. Як перша так і друга дає можливість видаляти непотрібні елементи, наприклад зайві елементи форматування, зображення чи блоки скриптів.

Приклад видалення для класу DOMDocument

foreach($ArticleList as $Article)
{
$DeleteList = array();
$ScriptList = $Article->getElementsByTagName("script");
foreach($ScriptList as $Script)
{
$DeleteList[]=$Script;
}

$ImagesList = $Article->getElementsByTagName("img");
foreach($ImagesList as $Img)
{
$result['image']=$Img->getAttribute('src');
}

foreach($DeleteList as $Item)
{
$Item->parentNode->removeChild($Item);
}
}

Приклад видалення для PHP Simple HTML DOM Parser

$junks = $text->find('script');
foreach($junks as $junk)
$junk->outertext = '';
$text = str_get_html($p->outertext);

Аналогічно, можна реалізувати парсинг, наприклад, на вбудованій мові 1С, яка теж має засоби роботи з HTML через DOM.

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

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

Додати новий коментар

Фото Капча
Введіть символи з картинки.