- Поисковые системы
- Практика оптимизации
- Трафик для сайтов
- Монетизация сайтов
- Сайтостроение
- Социальный Маркетинг
- Общение профессионалов
- Биржа и продажа
- Финансовые объявления
- Работа на постоянной основе
- Сайты - покупка, продажа
- Соцсети: страницы, группы, приложения
- Сайты без доменов
- Трафик, тизерная и баннерная реклама
- Продажа, оценка, регистрация доменов
- Ссылки - обмен, покупка, продажа
- Программы и скрипты
- Размещение статей
- Инфопродукты
- Прочие цифровые товары
- Работа и услуги для вебмастера
- Оптимизация, продвижение и аудит
- Ведение рекламных кампаний
- Услуги в области SMM
- Программирование
- Администрирование серверов и сайтов
- Прокси, ВПН, анонимайзеры, IP
- Платное обучение, вебинары
- Регистрация в каталогах
- Копирайтинг, переводы
- Дизайн
- Usability: консультации и аудит
- Изготовление сайтов
- Наполнение сайтов
- Прочие услуги
- Не про работу
Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий
Продолжаю учить пхп, теперь понемногу разбираюсь в парсинге. И я тут такое наговнокодил что самому страшно. У меня вот вопрос.
Если задача например следующая - забрать все абзацы на странице внутри id контент
Как мое творение можно оптимизировать и упростить?
$str = file_get_contents('http://code.mu/exercises/advanced/php/parsing/parsing-sajtov-regulyarnymi-vyrazeniyami-php/2/1.php');
//получаю блок контент
preg_match_all('~<div[^>]*?id="content"[^>]*?>(.+?)</div>~ms', $str, $matches2, PREG_SET_ORDER, 0);
//убираю лишнее
unset($matches2[0][0]);
//получаю все абзацы внутри контента
preg_match_all('~<p[^>]*?>(.*)</p>~mUs', $matches2[0][1], $matches3, PREG_SET_ORDER, 0);
//убираю лишнее
foreach ($matches3 as $lishnee){
unset($lishnee[0]);
var_dump($lishnee);
}
preg_match_all('~<div[^>]*?id="conten
Зачем preg_match_all если такой блок будет всего один?
Для отладки регулярок очень рекомендую сервис: https://regex101.com/
(.+?)</div>~
Если внутри этого блока будет ещё один блок то захватится только то что идёт до закрывающего тега вложенного блока.
Немного не правильно поставил вопрос.
Интересует - логика то правильная?
Сначала вычленяем нужный див, затем в нем ищем абзацы?
Итого две регулярки.
Или можно проще? Это просто моя первая попытка...
---------- Добавлено 15.05.2019 в 22:53 ----------
Если внутри этого блока будет ещё один блок то захватится только то что идёт до закрывающего тега вложенного блока.
А как этого избежать?
Dram,
Это вряд ли в тематике Вашего курса, но все же
$doc = new DOMDocument();
$doc->loadHTMLFile($t);
$doc->normalizeDocument();
$res=$doc->getElementById('content')->getElementsByTagName('p');
$n=array();
foreach($res as $p) $n[]=$doc->saveHTML($p);
var_dump($n);
Регулярки использовать для парсинга в принципе хорошо и правильно (сами предпочитаем), но dom дерево имеет свои плюсы (простота).
Готовые парсеры парсят обычно неплохо.
Но в инете редко встретишь валидный документ...
И есть еще одна неприятная проблема: время. Сейчас, некоторые, генерируют html размером в сотни и даже тысячи килобайт. И распарсивать его целиком немного долго и геморно. Т.е. дело доходило до того, что на обработку одного документа по несколько секунд требовалось...
Я, обычно, использую смешанный подход. Выбираю относительно небольшие блоки информации с использованием удобных функций, потом загоняю в парсер и получаю в более удобном виде.
Регулярки не использую. Менее удобно отлаживать.
edogs, спасибо за пример более элегантного способа. Начал его изучать плотнее. Решил попробовать вытащить абзацы с нужным классом и получил ошибку, почему?
Fatal error: Uncaught Error: Call to undefined method DOMElement::getElementsByClassName() in C:\OSPanel\domains\localhost\index.php on line 58
( ! ) Error: Call to undefined method DOMElement::getElementsByClassName() in C:\OSPanel\domains\localhost\index.php on line 58
edogs, спасибо за пример более элегантного способа. Начал его изучать плотнее. Решил попробовать вытащить абзацы с нужным классом и получил ошибку, почему?
Fatal error: Uncaught Error: Call to undefined method DOMElement::getElementsByClassName() in C:\OSPanel\domains\localhost\index.php on line 58
( ! ) Error: Call to undefined method DOMElement::getElementsByClassName() in C:\OSPanel\domains\localhost\index.php on line 58
Потому что там нет такой функции. https://www.php.net/manual/ru/book.dom.php - тут смотрите что есть.
Для задач выбора класса и/или вообще более сложных выборов можно использовать xpath
Обратите внимание - "ссылка 4" тут нет, ибо валидность.
Так же советуем (если тематика интересна) посмотреть на альтернативные классы html парсеров, не встроенных в php, они зачастую поинтереснее. С другой стороны на данном этапе можете не углубляться, тут важно знать сам факт возможности парсить не просто строковыми функциями, а через разбор dom дерева.
Большое спасибо!
для етого есть xpath. simple html dom parser. pquery