скрипт парсер сайтов на php
Парсинг и обработка веб-страницы на PHP: выбираем лучшую библиотеку
Задача спарсить и обработать необходимую информацию со стороннего сайта встает перед веб-разработчиком довольно часто и по самым разнообразным причинам: таким образом можно заполнять свой проект контентом, динамически подгружать какую-то информацию и так далее.
В таких случаях перед программистом встает вопрос: какую из десятков библиотек выбрать? В этой статье мы постарались рассмотреть самые популярные варианты и выбрать из них лучший.
Регулярные выражения
Даже не смотря на то, что «регулярки» — это первое, что приходит на ум, использовать их для настоящих проектов не стоит.
Да, с простыми задачами регулярные выражения справляются лучше всех, но его использование значительно затрудняется, когда нужно спарсить большой и сложный кусок HTML-кода, который, к тому же, не всегда соответствует какому-то определенному шаблону и вообще может содержать синтаксические ошибки.
Вместо «допиливания» своего регулярного выражения при каждом малейшем изменении кода рекомендуем использовать инструменты ниже — это и проще, и удобнее, и надежнее.
XPath и DOM
DOM и XPath не являются библиотеками в привычном смысле этого слова, это стандартные модули, которые встроены в PHP начиная с пятой версии. Именно отсутствие необходимости использовать сторонние решения делает их одними из лучших инструментов для парсинга HTML страниц.
На первый взгляд может показаться, что низкий порог входа — это не о них, некоторые места и вправду являются весьма сложными. Но это только на первый взгляд: стоит только немного разобраться с синтаксисом и базовыми принципами, как XPath тут же станет для вас инструментом для парсинга номер один.
Вот, например, код с использованием DOM и XPath, который ищет в разметке все теги и модифицирует их атрибуты src :
Тем не менее, данный вариант не лишен минусов — для парсинга используется движок, в первую очередь предназначенный для работы с XML, а XML и HTML хоть и являются очень похожими языками, но всё же различаются. Из этого вытекают специфические требования к разметке: например, все HTML теги должны быть закрыты.
Simple HTML DOM
Simple HTML DOM — PHP-библиотека, позволяющая парсить HTML-код с помощью удобных jQuery-подобных селекторов.
Она лишена главного недостатка XPath — библиотека умеет работать даже с невалидным HTML-кодом, что значительно упрощает работу. Вы также забудете о проблемах с кодировкой: все преобразования выполняются автоматически.
Как и JQuery, Simple HTML DOM умеет искать и фильтровать вложенные элементы, обращаться к их атрибутам и даже выбирать отдельные логические элементы кода, например, комментарии.
Несмотря на не самую высокую производительность, по сравнению с другими вариантами, Simple HTML DOM имеет самое большое русскоязычное комьюнити и наибольшую распространенность в рунете — для новичков это делает написание кода с её использованием значительно проще.
phpQuery
Как и Simple HTML DOM, phpQuery является PHP вариантом JQuery, но на этот раз более похожим на своего «старшего javascript-брата».
Портировано почти всё, что есть в JS-фреймворке: поддержка селекторов, атрибутов, манипуляций, обхода, плагинов, событий (в том числе имитации кликов и т.д.) и даже AJAX. Использовать можно как через PHP, так и через командную строку в виде отдельного приложения.
Более того, согласно нашим бенчмаркам, phpQuery оказался в 8 (!) раз быстрее Simple HTML DOM.
Вот небольшой пример на phpQuery, в котором происходит обработка заранее выбранных элементов списка ( li ):
Подробную документацию и больше примеров найдете на официальной странице в Google Code.
htmlSQL
htmlSQL — экспериментальная PHP библиотека, позволяющая манипулировать HTML-разметкой посредством SQL-подобных запросов.
Простейший пример, извлекающий атрибуты href и title всех ссылок (элементы a ) с классом list :
Как и с обычными mysql_ функциями, воспользовавшись методами fetch_array() или fetch_objects(), мы можем получить результат выполнения данного запроса в виде привычного ассоциативного массива или объекта.
Стоит также упомянуть о высоком быстродействии htmlSQL: часто она справляется в несколько раз быстрее phpQuery или того же Simple HTML DOM.
Тем не менее, для сложных задач вам может не хватить функциональности, а разработка библиотеки давно прекращена. Но даже несмотря на это, она всё ещё представляет интерес для веб-разработчиков: в ряде случаев значительно удобнее использовать язык SQL вместо CSS-селекторов. Особенно когда вы не знаете, что такое CSS-селекторы 😉
Вывод
В своем мини-исследовании мы пришли к выводу, что в большинстве случаев для парсинга лучше использовать библиотеку phpQuery: она быстрая, функциональная и современная.
С другой стороны, для совсем простых задач логично было бы использовать стандартные модули PHP, такие как XPath, DOM или, на крайний случай, регулярные выражения.
Что-то ещё?
Для PHP существуют ещё десятки разнообразных библиотек и инструментов для парсинга, но в этой статье мы рассмотрели только самые интересные, функциональные и производительные.
Подробнее о других способах парсинга средствами PHP можно прочитать в соответствующей теме на StackOverflow.
Если вы не используете PHP, то можете ознакомится с кратким списком похожих инструментов для других языков программирования:
Ассемблер: AsmXml.
Хинт для программистов: если зарегистрируетесь на соревнования Huawei Cup, то бесплатно получите доступ к онлайн-школе для участников. Можно прокачаться по разным навыкам и выиграть призы в самом соревновании.
Перейти к регистрации
Парсер html контента сайта на PHP
Решил привести статью в актуальный вид. Ранее на данной странице был представлен универсальный парсер HTML страниц на PHP. Но прошло уже более 4 лет, я наработал больше опыта в области разработки парсеров. И решил выложить новый пример PHP парсера с детальным разбором алгоритма работы.
Парсер прошлой версии носил гордое звание универсального, но это было весьма условное обозначение. Скрипт имел много ограничений, для его полноценного использования требовались знания в регулярных выражениях на PHP и JS.
Я подумал, подумал и решил, что более универсальным решением будет показать пример парсера на PHP и рассказать, как он работает. Так программисты, которые ранее не писали парсеров смогут решить свои задачи. А заказчики смогут понять возможности PHP в области парсинга сайтов и что реально можно требовать от программистов.
Парсер — это программа, которая анализирует входные текстовые данные, извлекает нужную информацию и на основе полученных данных выдаёт результат в заданном формате.
Общий алгоритм PHP парсинга предполагает, что ваш скрипт делает запрос по заданному адресу, получает ответ от сервера в виде HTML страницы, либо в каком-то другом текстовом формате, например CSV, JSON, XML. Далее полученная информация анализируется, из неё извлекаются (парсятся) нужные данные, на основе которых формируется результат. Полученные данные можно вывести на экран, либо записать в файл или БД.
Пример простого PHP парсера html контента
Предположим нам нужно спарсить цену на товары на сайте gearbest.com. Скрипт считывает заданную страницу, потом посредством регулярных выражений анализирует её контент и выделяет нужные нам куски HTML кода. Далее полученный результат выводится на экран.
index.php — основной файл PHP скрипта парсера. Код парсера актуален на момент публикации. Со временем HTML код сайта источника может меняться и регулярные выражения уже не будут к нему подходить.
Существуют разные способы установки скрипта. Я работал с ним из-под XAMPP. Но можно парсер запускать прямо с виртуального хостинга. Просто заливаете файл index.php к себе на сайт в какую-либо папку и обращаетесь к нему через адресную строку браузера. Предположим, что вы закинули скрипт в папку my-parser в корневой директории вашего хостинга. Тогда в адресной строке нужно набрать URL: http://вашдомен.ru/my-parser/.
Скриншот главной страницы парсера цены с сайта gearbest.com:
1. На главной странице парсера мы должны ввести адрес страницы товара. После нажатия на кнопку «Старт» страница перезагружается, отправляются данные формы на сервер и PHP скрипт делает запрос по заданному адресу с помощью библиотеки cURL.
За это действие отвечает функция curl_get_contents(), которая является аналогом стандартной PHP функции file_get_contents(), но с расширенным на основе cURL функционалом.
cURL — это расширение для PHP, которое обеспечивает поддержку библиотеки функций libcurl. Данный набор функций позволяет формировать POST и PUT запросы, скачивать файлы. Поддерживаются различные протоколы http, https, ftp и пр. Можно использовать прокси-серверы, cookies и аутентификацию пользователей. В общем, отличный инструмент для имитации действий пользователя в браузере.
cURL штука для разработки HTML парсеров очень полезная, и в одной из следующих статей я более подробно расскажу о приёмах работы с ней для целей парсинга.
2. Далее в функции get_gearbest_price() с помощью встроенной в PHP функции preg_match() и регулярных выражений проводится анализ ответной HTML страницы, полученной от стороннего сервера.
Обратите внимание, что скрипт видит страницу в текстовом формате и анализировать предстоит именно её HTML код.
3. На следующем этапе формируется и выводится на экран результат, полученный на основе данных после парсинга. В нашем случае это валюта и цена товара.
Таким образом, для успешной разработки парсеров на PHP программисту нужно уметь работать с библиотекой функций cURL и регулярными выражениями PHP.
Как парсить зашифрованные данные
В некоторых случаях сервера отдают HTML страницы в сжатом или защифрованном виде, например Accept-Encoding: gzip. При этом смена поддерживаемых форматов сжатия в запросе может не влиять на формат ответа.
В таких случаях нужно расшифровать ответ, например, стандартной PHP функцией gzdecode(). И дальше можно будет работать по старой схеме.
Данные, заширфованные по алгоритму base64 можно расшифровать функцией base64_encode().
PHP парсер HTML сайта бесплатно
Собственно ответ на вопрос, где взять PHP парсер сайтов бесплатно, простой — напишите его сами. Базовый алгоритм работы парсеров я выше разобрал в деталях.
Можно поискать уже готовые, написанные ранее кем-то решения вашей задачи. Но сделать парсер, который бы на автомате подходил ко всем вариантам, наверное, невозможно. Под каждый тип задач нужно разрабатывать свой конкретный продукт.
А для тех, кто не хочет париться с регулярными выражениями и настройками парсера, я готов провести его доработку за вас, но, конечно же, это будет стоить денег :-).
Итоговая стоимость услуг разработки определяется после получения конкретного технического задания. Цена устанавливается строго перед началом выполнения работы, в ходе рабочего процесса финансовые условия не изменяются. Работаю по 100% предоплате. Минимальный заказ составляет 2000 рублей.
Часто цена парсера выходит довольно высокой, а связано это с тем, что разработка получается уникальной, заточенной под конкретного заказчика. Разные бывают варианты входных дынных, требуется индивидуальный формат результата на выходе.
В этом случае формально тоже можно получить парсер для себя бесплатно. Например, цена разработки парсера получилась 9 000 рублей. Вы ищете 9 человек с аналогичной проблемой и собираете с них по 1000 рублей, заказываете разработку парсера. Потом делаете 10 копий, 1 себе и 9 отдаёте вашим знакомым.
В следующем цикле статей я покажу примеры реализации более сложных парсеров с авторизацией, сбор фото, работа с AJAX, парсинг ВК и т.п.
В общем, дорогие мои читатели, чем смог тем помог, читайте, учитесь и не забывайте ставить ссылки на блог Предприимчивого Человека.
Пишем быстрый PHP парсер (scraper)
Так сильно увлекаясь парсингом сайтов, я удивляюсь самому себе, насколько мало информации я публикую на эту тему. Сегодня я решил немного поправить эту несправедливость. В этой статье я хочу показать, как сделать быстрый парсер на PHP, в частности парсер фильмов с кинопоиска средствами PHP.
Примите к сведению, что при парсинге мы полагаемся на определённую DOM-структуру сайта, определённые css-селекторы в HTML-разметке страницы. Потому, держите в уме вероятность того, что структура сайта в будущем будет обновлена, и парсер, возможно перестанет работать. И, вероятно, с кодом из этой статьи случится то же самое, когда сайт-донор обновит разметку.
Большинство PHP-разработчиков, хоть раз в жизни делали парсер. Будь то с использованием file_get_contents, или curl, но, уверен, каждый хоть раз в жизни парсил информацию из Web-а. И это не удивительно, ведь очень часто появляется необходимость в копировании большого количества информации со сторонних сайтов, особенно для новых, пустых сайтов, нуждающихся в автоматическом наполнении.
Алгоритм парсинга аналогичен тому, что вы бы открыли нужный URL в браузере, просмотрели бы сайт, и скопировали бы нужную вам информацию себе. Но если таких действий нужно будет проделать несколько тысяч раз, то это становится довольно затруднительно. И, к счастью, это можно легко автоматизировать с помощью скриптов. В этой статье я покажу, как написать быстрый парсер, используя асинхронные запросы.
Зачем люди пишут парсеры
Но, это только один пример, придуманный сходу. На самом же деле, парсеры используются почти в каждом проекте: для наполнения сайта данными, для актуализации и обновления. Потому, их применение достаточно широко, и интересно. Потому знать, как писать парсер на php нужно. А если вы ещё освоите многопоточный парсинг, то жизнь станет ещё проще ^^.
Задача
В этой статье я напишу простой WEB-парсер информации о фильме с Кинопоиска, который будет получать детали этого фильма:
Настройка проекта
Перед тем, как начать, с помощью композера нужно установить несколько зависимостей.
Сначала, установим асинхронный HTTP-клиент buzz-react. Это простой PSR-7 HTTP клиент, который поможет выполнять асинхронные HTTP-запросы.
Для того, чтобы из целой html-страницы получить определённые «куски» с нужной для нас информацией, используем библиотеку для парсинга по DOM-структуре. Я использую DiDOM
Теперь, можем начинать. Для начала, напишем такой код:
Делаем запросы
Интерфейс класса Clue\React\Buzz\Browser достаточно простой и прямолинейный. Имена методов соответствуют HTTP-методам, которые он выполняет: GET-метод соответствует методу get(), GET-post(), PUT-put() и т.д. И каждый из этих методов возвращает Promise (если вы знакомы с JavaScript, или ранее работали с ReactPHP, то это не должно вызвать у вас вопросов). Если вы не знаете, что это, то на даном этапе объяснения не имеют большого смысла, дальше будет пример, после которого всё станет понятно.
Как вы можете заметить, алгоритм парсинга достаточно прост:
Работа с DOM документа
Страница фильма, которую мы парсим не требует никакой авторизации. Если посмотреть на исходный код этой страницы, то можно увидеть, что все данные, за которыми мы охотимся, доступны внутри HTML. Иногда бывают случаи, когда анализ сайта, его противопарсинговые защиты, обход алгоритмов защиты и т.д. занимают на порядок больше времени, чем написание самого кода парсера.
Теперь, когда мы научились получать ответ (содержимое WEB-страницы), можем начать работу с DOM-ом этого документа. Для этого, как я и ранее писал, я буду использовать Didom, подробнее о котором вы можете почитать здесь.
Заголовки (Title, Alternative Title)
Заголовок может быть получен с тега h1 (который единственнный на всей странице).
Таблица параметров
А ещё из разметки можно увидеть, что нужные нам параметры находятся во втором столбце (td) каждой из строк таблицы (tr). Но, нам не нужно сильно запариваться по поводу парсинга информации, так как можно увидеть, что в каждой строке таблицы есть только по одной ссылке, которые, как раз таки, и содержат внутри себя текст параметров.
Для этого, напишем код, получая сначала все строки таблицы, а потом обращаясь к ним по индексу:
Время и рейтинг (time, rating)
Информация о времени находится в той же таблице, которую парсили в прошлом шаге. Для получение данных, можно, как и в прошлом коде, обратиться по индексу:
Однако, изучив детальнее, можно увидеть, что у блока «время» есть уникальный идентификатор runtime, которым мы и воспользуемся.
И в этом случае, код будет выглядеть:
И, аналогично поступим с рейтингом. Он, правда, не имеет тега id, однако, класс блога рейтинга уникальный, и не повторяется на странице, потому будем обращаться по нему:
Итого, код парсера будет выглядеть так:
Написание класса парсера
Теперь пришло время собрать все части спаршеных данных вместе. Логина по выполнению запроса может быть помещена в отдельную функцию/класс, а так же, нужно добавить более гибкую функциональность, добавив возможность указания разных URL-адресов. Для этого, создадим класс KinopoiskParser
Теперь, наконец-то, можем попробовать этот парсер в действии:
В этом коде мы создали объект парсера, передали его методу URL-адреса для парсинга, после чего, запустили обработчик цикла событий. События будут обрабатываться до тех пор, пока все запросы не будут выполнены, и результаты, в которых нуждаемся, не спаршены с HTML-разметки. Как результат, эти запросы выполняются параллельно, потому, итоговое время выполнения скрипта будет равно самому медленному из наших запросов.
Результат будет выглядеть примерно так:
Дальше вы можете продолжать писать парсер как угодно: разделив его на несколько файлов, добавить запись результатов в базу данных. Главная цель этой статьи была показать, как выполнять асинхронные запросы в PHP и обрабатывать ответ с помощью DOM-парсинга.
Добавление таймайта
После чего, модифицируем метод parse() так, чтобы он мог принимать таймаут.
Для примера, если мы не желаем ждать дольше, чем 3 секунды, напишем код:
Резюме
Subscribe to Блог php программиста: статьи по PHP, JavaScript, MySql
Get the latest posts delivered right to your inbox
Как я html-парсер на php писал, и что из этого вышло. Вводная часть
Сегодня я хочу рассказать, как написать html парсер, а также с какими проблемами я столкнулся, разрабатывая подобный парсер на php. А проблем было много. И в первой части я расскажу о проектировании парсера, и о возникших проблемах, ведь html парсер отличается от парсера привычных всем языков программирования.
Введение
Я старался написать текст этой статьи максимально понятно, чтобы любой, кто даже не знаком с общим устройством парсеров мог понять то, как работает html парсер.
Здесь и далее в статье я буду называть документ, содержащий html просто «Документ».
Dom дерево, находящееся в элементе, будет называться «Подмассив».
Что должен делать парсер?
Давайте сначала определимся, что должен делать парсер, чтобы в будущем отталкиваться от этого при разработке. А именно, парсер должен:
Впрочем, это мелочи. Основного функционала вполне хватит, чтобы поломать голову пару ночей напролет.
Но тут есть проблема, с которой я столкнулся сразу же: Html — это не просто язык, это язык гипертекста. У такого языка свой синтаксис, и обычный парсер не подойдет.
Разделяй и властвуй
Для начала, нужно разделить работу парсера на два этапа:
Для описания первого этапа я нарисовал схему, которая наглядно показывает, как обрабатываются данные на первом этапе:
Пишем парсер контента на PHP
Чтобы написать хороший и работоспособный скрипт для парсинга контента нужно потратить немало времени. А подходить к сайту-донору, в большинстве случаев, стоит индивидуально, так как есть масса нюансов, которые могут усложнить решение нашей задачи. Сегодня мы рассмотрим и реализуем скрипт парсера при помощи CURL, а для примера получим категории и товары одного из популярных магазинов.
Если вы попали на эту статью из поиска, то перед вами, наверняка, стоит конкретная задача и вы еще не задумывались над тем, для чего ещё вам может пригодится парсер. Поэтому, перед тем как вдаваться в теорию и непосредственно в код, предлагаю прочесть предыдущею статью – парсер новостей, где был рассмотрен один из простых вариантов, да и я буду периодически ссылаться на неё.
Работать мы будем с CURL, но для начала давайте разберёмся, что эта аббревиатура обозначает. CURL – это программа командной строки, позволяющая нам общаться с серверами используя для этого различные протоколы, в нашем случаи HTTP и HTTPS. Для работы с CURL в PHP есть библиотека libcurl, функции которой мы и будем использовать для отправки запросов и получения ответов от сервера.
Как можно увидеть из скриншота все категории находятся в ненумерованном списке, а подкатегории:
Внутри отельного элемента списка в таком же ненумерованном. Структура несложная, осталось только её получить. Товары мы возьмем из раздела «Все телефоны»:
На странице получается 24 товара, у каждого мы вытянем: картинку, название, ссылку на товар, характеристики и цену.
Пишем скрипт парсера
Если вы уже прочли предыдущею статью, то из неё можно было подчеркнуть, что процесс и скрипт парсинга сайта состоит из двух частей:
Основной метод, который у нас будет – это getPage() и у него всего один обязательный параметр URL страницы, которой мы будем парсить. Что ещё будет уметь наш замечательный метод, и какие значения мы будем обрабатывать в нем:
Конечно, обрабатываемых значений много и не всё мы будем использовать для нашей сегодняшней задачи, но разобрать их стоит, так как при парсинге больше одной страницы многое выше описанное пригодится. И так добавим их в наш скрипт:
Как видите, у всех параметров есть значения по умолчанию. Двигаемся дальше и следующей строчкой напишем кусок кода, который будет очищать файл с куками при запросе:
Так мы обезопасим себя от ситуации, когда по какой-либо причине не создался файл.
Для работы с CURL нам необходимо вначале инициализировать сеанс, а по завершению работы его закрыть, также при работе важно учесть возможные ошибки, которые наверняка появятся, а при успешном получении ответа вернуть результат, сделаем мы это таким образам:
После того, как мы инициализировали соединения через функцию curl_setopt(), установим несколько параметров для текущего сеанса:
Кстати очень удобный сервис, позволяющий отладить обращения к серверу. Так как, например, для того что бы узнать свой IP или заголовки отправляемые через CURL, нам бы пришлось бы писать костыль.
Если вывести на экран, то у вас должна быть похожая картина:
Если произойдет ошибка, то результат будет выглядеть так:
При успешном запросе мы получаем заполненную ячейку массива data с контентом и информацией о запросе, при ошибке заполняется ячейка error. Из первого скриншота вы могли заметить первую неприятность, о которой я выше писал контент сохранился не в переменную, а отрисовался на странице. Чтобы решить это, нам нужно добавить ещё один параметр сеанса CURLOPT_RETURNTRANSFER.
Обращаясь к страницам, мы можем обнаружить, что они осуществляют редирект на другие, чтобы получить конечный результат добавляем:
Теперь можно увидеть более приятную картину:
Для того, чтобы получить заголовки ответа, нам потребуется добавить следующий код:
Мы отключили вывод тела документа и включили вывод шапки в результате:
Для работы со ссылками с SSL сертификатом, добавляем:
Предлагаю проверить, а для этого я попробую вытянуть куки со своего сайта:
Всё получилось, двигаемся дальше и нам осталось добавить в параметры сеанса: прокси, заголовки и возможность отправки запросов POST:
Парсим категории и товары с сайта
Теперь, при помощи нашего класса Parser, мы можем сделать запрос и получить страницу с контентом. Давайте и поступим:
Следующим шагом разбираем пришедший ответ и сохраняем название и ссылку категории в результирующий массив:
Чуть более подробно работу с phpQuery я разобрал в первой статье по парсингу контента. Если вкратце, то мы пробегаемся по DOM дереву и вытягиваем нужные нам данные, их я решил протримить, чтобы убрать лишние пробелы. А теперь выведем категории на экран:
В результате мы получили все ссылки на категории. Для получения товаров используем тот же принцип:
Получаем страницу, тут я увеличил время соединения, так как 5 секунд не хватило, и разбираем её, парся необходимый контент:
Теперь проверим, что у нас получилось, и выведем на экран: