Парсер/граббер статей на PHP и проблемы его реализации

archive view archive save

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

В сети по запросу "парсер статей на PHP" или "парсер контента на PHP" дохерище множественных примеров парсеров т.с. на скорую руку, тут тебе и "Пишем простейший ПАРСЕР контента на PHP", и "Парсим контент к себе на сайт простейшим способом", и "Парсер на PHP – это просто".

Да, парсер на PHP – это просто, но при условии если от него требуется выполнение простых и не сложных задач, например сбор со страницы всех веб-ссылок или тупая вырезка контента как он есть на чужом сайте и без всякой дополнительной обработки сохранение его на сайте своём, в таких случаях можно обойтись десятком строк PHP кода (т.с.: х.як-х.як и в продакшын).

В ходе реализации любого парсера/граббера на PHP, который будет автоматически грабить чужие статьи и публиковать их на конечном сайте, нам в обязательном порядке придётся дать однозначные ответы на перечисленные ниже вопросы.

Вопрос №1 - Источник

Первым делом нужно определится с источником ссылок на материалы, которые мы будем грабить/парсить на свой сайт - это может быть либо XML-карта сайта, либо RSS-лента, либо же главная страница блога например.

Это первая часть с которой нам нужно начинать написание парсера/граббера на PHP и от выбора источника ссылок (XML-карта, RSS-лента и т.д.) может зависеть, как размер самого участка кода отвечающего за парсинг источника ссылок на материалы для парсинга, так и своевременность кражи/парсинга материала.

Под своевременностю кражи/парсинга материала подразумевается временной промежуток между публикацией материала на сайте-доноре и публикацией его на сайте-воре. Так например если в качестве источника ссылок мы выбираем XML-карту сайта мы вероятно сократим расходы на написание PHP кода благодаря простой XML-структуре, но можем с опозданием в сутки или более получать контент имхо на некоторых сайтах XML-карты обновляются раз в сутки или более того. Парсинг кратких анонсов главной страницы блога обойдётся дороже по количеству PHP кода и к тому же может давать сбои при смене ХТМЛ-разметки имхо их поиск и парсинг выполняется по определённым маркерам, например CSS-классам и идентификаторам (class="foo", id="bar"), как собственно и при парсинге самого материала.

На мой личный взгляд идеальным вариантом будет RSS-лента имхо почти все они как правило обновляются мгновенно за исключением лент от сторонних RSS-сервисов/агрегаторов таких, как например FeedBurner. FeedBurner также читает ленту новостей с сайта донора, но с регулярностью, которую указал владелец аккаунта FeedBurner. Ленту, которую читает FeedBurner, если она не указана в коде сайта, можно попробовать найти опытным путём, однако, владелец сайта донора может установить с неё редирект для всех кроме, тех у кого юзверь-агент не равен "FeedBurner" - это ограничение можно обойти подделав юзверь-агент использовав CURL вместо DOMDocument, однако, кроме юзверь-агента дополнительно может проверятся и диапазон ИП-адресов, который на уровне языка программирования PHP неподделать.

Вопрос №2 - Свежесть

Следует резонно предполложить, что наш парсер/граббер контента должен парсить материалы/статьи с сайта-донора только по тем ссылкам, которые ещё не обрабатывались и небыли добавлены на наш сайт.

Перед началом парсинга статьи нужно достоверно знать, что такая статья ещё не была "скопипизжена", а для этого видимо нужно проверять текущую дату/время/ссылку/вступительный текст и на основе этих данных формировать хеш-суму которую сохранять локально (в имени файла например, а не в самом файле) или в БД.

Ещё как вариант, проверять алиас материала непосредственно перед сохранением статьи в БД, однако в таком случае нужно будет делать выборку, что при большом числе материалов будет создавать дополнительную нагрузку на сервер БД.

При сипользовании временных файлов для проверки свежести статьи нужно будет также подумать о удалении старых контрольных файлов статей, которых уже нет в ленте новостей, чтобы не забивать ими дисковое пространство.

Вопрос №3 - Категория

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

Таким образом нам либо нужно делать на каждую категорию отдельный парсер, либо усложнять его отдельными конфигурационными параметрами/массивами со списком ссылок лент новостей источника и сопоставленными им ИД категорий конечного сайта.

Более простое решение - это сваливать все статьи в одну категорию и потом каждый из материалов просто помечать тегами таким образом объенияя их.

Вопрос №4 - Форматирование

Если с помощью DOMDocument получать исключительно только "голый" текст статей, т.е. без тегов форматирования, то вместе с разметкой мы автоматом теряем все изображения, youtube-видео, цитаты между тегами <blockquote>|<cite> - потому поллучение только одного сырого текста не является самым оптимальным вариантом.

Кроме того, получив только текст без тегов форматирования абзацы мы сможем без особых усилий пересоздать только если каждый из абзацов начинался с новой строки и ХТМЛ код не был оптимизирован никакими оптимизаторами. В случае же если ХТМЛ код был оптимизирован какими-то оптимизаторами и весь он идёт в одну строку, то в таком случае мы получим один здоровенный абзац текста, который после нужно будет дробить на части, что может дорого обойтись.

Потому, видимо, целесообразнее будет получать текст статьи вместе с тегами ХТМЛ форматирования, которые при необходимости потом чистить от стилей и назначенных классов, например с помощью "HTML Purifier".

Вопрос №5 - Изображения

Ещё одной из проблем автоматического парсинга являются пути к изображениям. Например, хорошо если в качестве путей к изображениям указаны полные УРЛ-адреса и перед парсером, а значит и перед программистом, не стоит задача корректировки URL для изображения, если же указаны относительные ссылки, то как минимум придётся в src="https://static.itmag.pro/" дописывать имя домена сайта-донора.

Задача усложняется если нужно скачивать изображение на свой сервер и там ещё с ним (изображением) дополнительно совершать какие-то манипуляции, - например изменение размера изображения, оптимизация конвертация и т.д., а потом изменять URL к изображению в самом тексте материала.

Вопрос №6 - Транслитерация

Получив текст материала нам нужно будет придумывать, какой алиас назначить материалу - либо сохранить оригинальный либо создавать свой собственный из заголовка путём его транслитерации.

Оригинальный алиас может быть либо в виде цифр, что с точки зрения СЕО как бы не совсем правильно (но не смертельно), либо в виде уже транслитированного текста, а иногда может быть и в виде кириллического текста. В последних двух случаях алиасы могут быть либо лаконичными (короткими) либо чересчур содержательными (длинными) - нужно следить за длиной алиаса.

Вопрос №7 - Разделитель

В большинстве блогов текст материала делится на несколько частей - вступительная часть, обычно до 145-170-255 знаков (гугл в результатах поиска выводит 145, остальное обрезает), и, основная часть материала.

В разных движках в качестве раделителя вступительной и основной части материала могут использоваться различные маркеры по которым движок определяет где нужно резать текст, например в движке Joomla! таким маркером является ХТМЛ тег "<hr id="system-readmore" />", в некоторых других, например Wordpress, используется ХТМЛ-комментарий <!--more-->.

Саму метку разделителя нужно вставлять между ХТМЛ-тегами и ни в коем случае внутри ХТМЛ-тега! ИМХО сама метка и всё что идёт после неё будет обрезано, а если мы вставим метку разделителя например вот так <p>Вступительный текст ... <!--more--></p>, то на странице где выводятся анонсы мы получим "<p>Вступительный текст ... " невалидный код и вероятнее всего "кривое" отображение страницы.

Вопрос №8 - МЕТА-данные

Нужны ли нам мета-данные - <meta name="description" content="bla-blu-bla" /> и <meta name="keywords" content="bla, blu, bla" />?

Поисковые роботы обычно умеют самостоятельно составлять и выводить в результатах поиска краткое описание близкое к тому, которое искал человек, и как правило это не всегда может быть то описание, что указывалось в <meta name="description" content="bla-blu-bla" /> или в <meta name="keywords" content="bla, blu, bla" />.

Нужно ли их указывать? Х/З товарищи! Во-первых, обычно с давних пор считается хорошим тоном заполнять содержимое этих параметров. Во-вторых, заполнение этих параметров может быть полезным если на странице есть модуль похожих статей, который при выборке похожих материалов ориентируется содержимое в МЕТА-данных.

Где взять более менее ревалентный текст для "description" и "keywords" если они не были указаны на странице источнике? Самым простым вариантом будет взять "description" из первого абзаца статьи, а "keywords" из заголовка.

Вопрос №9 - Уведомления

Стоит также определится, хотим ли мы получать уведомления о добавляемых парсером статьях. Если хотим получать уведомления, то только об успешно добавленых или получать также и о неудачных попытках парсинга?


Комментарии   

Олегатор
0 #3 Олегатор 06.03.2017 15:52
Цитирую АдМинь БагоИскатель:
DOMDocument коряво работает с HTML5 контентом и сыпет мессагами:
Код:[02-Mar-2017 12:31:43 Europe/Kiev] PHP Warning: DOMDocument::loadHTMLFile(): Tag nav invalid in test.html, line: 321 in /var/www/test.php on line 72
[02-Mar-2017 12:31:43 Europe/Kiev] PHP Warning: DOMDocument::loadHTMLFile(): Tag article invalid in test.html, line: 345 in /var/www/test.php on line 72
[02-Mar-2017 12:31:43 Europe/Kiev] PHP Warning: DOMDocument::loadHTMLFile(): Tag time invalid in test.html, line: 428 in /var/www/test.php on line 72
[02-Mar-2017 12:31:43 Europe/Kiev] PHP Warning: DOMDocument::loadHTMLFile(): Unexpected end tag : div in test.html, line: 627 in /var/www/test.php on line 72
[02-Mar-2017 12:31:43 Europe/Kiev] PHP Warning: DOMDocument::loadHTMLFile(): Tag footer invalid in test.html, line: 688 in /var/www/test.php on line 72

html5-php: https://github.com/Masterminds/html5-php должно помочь
Цитировать
АдМинь БагоИскатель
0 #2 АдМинь БагоИскатель 04.03.2017 08:49
DOMDocument коряво работает с HTML5 контентом и сыпет мессагами:
Код:[02-Mar-2017 12:31:43 Europe/Kiev] PHP Warning: DOMDocument::loadHTMLFile(): Tag nav invalid in test.html, line: 321 in /var/www/test.php on line 72
[02-Mar-2017 12:31:43 Europe/Kiev] PHP Warning: DOMDocument::loadHTMLFile(): Tag article invalid in test.html, line: 345 in /var/www/test.php on line 72
[02-Mar-2017 12:31:43 Europe/Kiev] PHP Warning: DOMDocument::loadHTMLFile(): Tag time invalid in test.html, line: 428 in /var/www/test.php on line 72
[02-Mar-2017 12:31:43 Europe/Kiev] PHP Warning: DOMDocument::loadHTMLFile(): Unexpected end tag : div in test.html, line: 627 in /var/www/test.php on line 72
[02-Mar-2017 12:31:43 Europe/Kiev] PHP Warning: DOMDocument::loadHTMLFile(): Tag footer invalid in test.html, line: 688 in /var/www/test.php on line 72
Цитировать
Guest
0 #1 Guest 03.03.2017 02:01
К статье бы добавить список РНР-библиотек полезных для парсинга!
Цитировать

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

АХТУНГ! Все комменты гостей модерасятся модерастом.
  1. Мессаги исключительно рекламного содержания, либо содержащие только одни оценочные суждения типа "круто" ("отлично", "спасибо", "автор дебил" и т.п.) не публикуются;
  2. Злостным спамерам, пранкерам и прочей сетевой нечисти рекомендуем напрасно не тратить своего времени и удовлетворять свои больные фантазии на специализированных Интернет ресурсах!;
  3. Разумная обоснованная критика, замечания, дополнения приветствуются. Поля помеченные символом * обязательны к заполнению.


Защитный код
Обновить

Комментарии в блоге
Новое на форуме