Парсер сайтов PHP

Решил привести статью в актуальный вид. Ранее на данной странице был представлен универсальный парсер HTML страниц на PHP. Но прошло уже более 4 лет, я наработал больше опыта в области разработки парсеров. И решил выложить новый пример PHP парсера с детальным разбором алгоритма работы.

Парсер прошлой версии носил гордое звание универсального, но это было весьма условное обозначение. Скрипт имел много ограничений, для его полноценного использования требовались знания в регулярных выражениях на PHP и JS.

Я подумал, подумал и решил, что более универсальным решением будет показать пример парсера на PHP и рассказать, как он работает. Так программисты, которые ранее не писали парсеров смогут решить свои задачи. А заказчики смогут понять возможности PHP в области парсинга сайтов и что реально можно требовать от программистов.

Парсер — это программа, которая анализирует входные текстовые данные, извлекает нужную информацию и на основе полученных данных выдаёт результат в заданном формате.

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

Пример простого PHP парсера html контента

Предположим нам нужно спарсить цену на товара на сайте gearbest.com. Скрипт считывает заданную страницу, потом посредством регулярных выражений анализирует её контент и выделяет нужные нам куски HTML кода. Далее полученный результат выводится на экран.

<?php Error_Reporting(E_ALL & ~E_NOTICE); mb_internal_encoding(«UTF-8»); set_time_limit(0); // Попытка установить своё время выполнения скрипта /* — 1 — Инициализируем переменные для запроса */ $time_start = time(); $error = array(); $error_page = array(); $action = 0; $gearbest_url = «»; $charset = «UTF-8»; // Исходная кодировка страницы $uni_name = date(«d-m-Y-H-i-s», time()); /* — 1.1 — Переопределяем переменные на основе GET или POST параметров */ if(isset($_REQUEST)) $gearbest_url = trim($_REQUEST); if(isset($_REQUEST)) $action = $_REQUEST; /* — 1.2 — Загрузка страницы при помощи cURL */ function curl_get_contents($page_url, $base_url, $pause_time, $retry) { /* $page_url — адрес страницы-источника $base_url — адрес страницы для поля REFERER $pause_time — пауза между попытками парсинга $retry — 0 — не повторять запрос, 1 — повторить запрос при неудаче */ $error_page = array(); $ch = curl_init(); curl_setopt($ch, CURLOPT_USERAGENT, «Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0»); //curl_setopt($ch, CURLOPT_COOKIEJAR, str_replace(«\\», «/», getcwd()).’/gearbest.txt’); //curl_setopt($ch, CURLOPT_COOKIEFILE, str_replace(«\\», «/», getcwd()).’/gearbest.txt’); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // Автоматом идём по редиректам curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0); // Не проверять SSL сертификат curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0); // Не проверять Host SSL сертификата curl_setopt($ch, CURLOPT_URL, $page_url); // Куда отправляем curl_setopt($ch, CURLOPT_REFERER, $base_url); // Откуда пришли curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // Возвращаем, но не выводим на экран результат $response = curl_exec($ch); $info = curl_getinfo($ch); if($info != 200 && $info != 404) { $error_page = array(1, $page_url, $info); if($retry) { sleep($pause_time); $response = curl_exec($ch); $info = curl_getinfo($ch); if($info != 200 && $info != 404) $error_page = array(2, $page_url, $info); } } $response = $info; $response = $error_page; curl_close($ch); return $response; } /* — 1.3 — Парсинг цены */ function get_gearbest_price($gearbest_url) { /* $gearbest_url — адрес страницы товара на Gearbest */ $res_arr = array(); $res_arr = array(); $base_url = «https://www.gearbest.com»; $response_arr = curl_get_contents($gearbest_url, $base_url, 5, 1); $page = $response_arr; $page_code = $response_arr; $res_arr = $response_arr; //file_put_contents(‘page.txt’, $page); //$page = file_get_contents(‘page.txt’); if(!empty($page) && $page_code == 200) { if($charset != «UTF-8») { $page = iconv(«WINDOWS-1251», «UTF-8//IGNORE», $page); } $buffer = array(); $regexp = «/(id=\»unit_price\»\s*data-orgp=\»(.*)\»)|(class=\»my_shop_price new_shop_price\»\s*data-orgp=\»(.*?)\»\s*id=\»unit_price\»)/Us»; preg_match($regexp, $page, $buffer); $res_arr = $buffer ? $buffer : $buffer; $regexp = «/bizhong=\»(.*)\»>/Us»; $buffer = array(); preg_match($regexp, $page, $buffer); $res_arr = $buffer; $res_arr = »; } else { $res_arr = 0; $res_arr = ‘nodata’; $res_arr = ‘Ошибка загрузки страницы’; } return $res_arr; } /* — 1.4 — Вывод данных в HTML */ /* — 1.4.1 — Вывод полученых цен */ function price_list_html($price_list) { echo ‘<p>Цена: ‘ . $price_list . ‘ <span class=\»currency\»>’ . $price_list . ‘</span></p>’; } /* — 1.4.2 — Вывод ошибок */ function error_list_html($error) { if (!empty($error)) { echo «<p>Во время обработки запроса произошли следующие ошибки:</p>\n»; echo «<ul>\n»; foreach($error as $error_row) { echo «<li>» . $error_row . «</li>\n»; } echo «</ul>\n»; echo «<p>Статус: <span class=\»red\»>FAIL</span></p>\n»; } else { echo «<p>Статус: <span class=\»green\»>OK</span></p>\n»; } } /* — 1.4.3 — Вывод ошибок загрузки страниц */ function error_page_list_html($error_page) { if (!empty($error_page)) { echo «<ul>\n»; foreach($error_page as $error_row) { echo «<li> . «] » . $error_row . » — » . $error_row . «</li>\n»; } echo «</ul>\n»; } } /* — 1.4.4 — Вывод работы скрипта */ function run_time_html($time_start) { if(!empty($time_start)) echo «<!—p>Время работы: » . (time() — $time_start) . «</p—>\n»; } /* — 2 — Получение контента из каталога Gearbest */ if($action) { // если ошибок нет и данные формы поиска получены if(!empty($gearbest_url)) { $gearbest_url = trim($gearbest_url); $din_url = $gearbest_url; $res_arr = get_gearbest_price($din_url); $price_list = $res_arr; $error_page = $res_arr; $error = $res_arr; } else { $error = «Не задан адрес страницы с товаром»; } } /* — 3 — Вывод результатов работы парсера */ ?> <!doctype html> <html> <head> <title>Парсер цены товара на Gearbest.com</title> <meta http-equiv=»Content-Type» content=»text/html; charset=utf-8″> <!—meta name=»robots» content=»noindex,nofollow»—> </head> <body> <style> .wrapper { max-width: 600px; margin: 0 auto; } h1 { text-align: center; } .action_form { max-width: 560px; margin: 0 auto; } .action_form input { width: 100%; } input { font-size: 1em; min-height: 36px; box-sizing: border-box; } input { padding: 8px 12px; margin: 12px auto; font-size: 1.2em; font-weight: 400; line-height: 1.2em; text-decoration: none; display: inline-block; cursor: pointer; border: 2px solid #007700; border-radius: 2px; background-color: transparent; color: #007700; } input:hover { background-color: #009900; color: #fff; } .result { border: 1px dotted #000; width: 100%; height: auto; overflow-y: auto; margin: 0px auto; padding: 10px; } .copyright { text-align: center; } .copyright a { color: #000; } .copyright a:hover { text-decoration: none; } .red { color: #770000; } .green { color: #007700; } </style> <div class=»wrapper»> <h1>Парсер цены товара на Gearbest.com</h1> <form class=»action_form» action=»» method=»post»> <input type=»hidden» name=»action» value=»1″ /> <input type=»text» name=»gearbest_url» value =»<?php if(!empty($gearbest_url)) echo $gearbest_url; ?>» placeholder=»URL страницы товара» /> <input type=»submit» name=»submit» value=»Старт» /> </form> <div class=»result»> <?php if($action && !empty($price_list)) { price_list_html($price_list); } ?> </div> <div class=»errors_block»> <?php error_page_list_html($error_page); error_list_html($error); run_time_html($time_start); ?> </div> <div class=»copyright»>&copy Идея и реализация — <a href=»https://seorubl.ru/» target=»_blank» title=»Записки Предприимчивого Человека» rel=»generator»>ПЧ</a> // 16.04.2017 г.</div> </div> </body> </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.

PHP парсер HTML сайта бесплатно

Собственно ответ на вопрос, где взять PHP парсер сайтов бесплатно, простой — напишите его сами. Базовый алгоритм работы парсеров я выше разобрал в деталях.

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

А для тех, кто не хочет париться с регулярными выражениями и настройками парсера, я готов провести его доработку за вас, но, конечно же, это будет стоить денег :-).

Итоговая стоимость услуг разработки определяется после получения конкретного технического задания. Цена устанавливается строго перед началом выполнения работы, в ходе рабочего процесса финансовые условия не изменяются. Работаю по 100% предоплате. Минимальный заказ составляет 2000 рублей.

Часто цена парсера выходит довольно высокой, а связано это с тем, что разработка получается уникальной, заточенной под конкретного заказчика. Разные бывают варианты входных дынных, требуется индивидуальный формат результата на выходе.

В этом случае формально тоже можно получить парсер для себя бесплатно. Например, цена разработки парсера получилась 9 000 рублей. Вы ищете 9 человек с аналогичной проблемой и собираете с них по 1000 рублей, заказываете разработку парсера. Потом делаете 10 копий, 1 себе и 9 отдаёте вашим знакомым.

В следующем цикле статей я покажу примеры реализации более сложных парсеров с авторизацией, сбор фото, работа с AJAX, парсинг ВК и т.п.

В общем, дорогие мои читатели, чем смог тем помог, читайте, учитесь и не забывайте ставить ссылки на блог Предприимчивого Человека.

Парсер html контента сайта на PHP 4 (80%) 5 votes
Не жмись! С друзьями ссылкой поделись:

Парсинг и обработка веб-страницы на PHP: выбираем лучшую библиотеку

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

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

Регулярные выражения

Даже не смотря на то, что «регулярки» — это первое, что приходит на ум, использовать их для настоящих проектов не стоит.

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

Вместо «допиливания» своего регулярного выражения при каждом малейшем изменении кода рекомендуем использовать инструменты ниже — это и проще, и удобнее, и надежнее.

XPath и DOM

DOM и XPath не являются библиотеками в привычном смысле этого слова, это стандартные модули, которые встроены в PHP начиная с пятой версии. Именно отсутствие необходимости использовать сторонние решения делает их одними из лучших инструментов для парсинга HTML страниц.

На первый взгляд может показаться, что низкий порог входа — это не о них, некоторые места и вправду являются весьма сложными. Но это только на первый взгляд: стоит только немного разобраться с синтаксисом и базовыми принципами, как XPath тут же станет для вас инструментом для парсинга номер один.

Вот, например, код с использованием DOM и XPath, который ищет в разметке все теги

и модифицирует их атрибуты src:$dom = new DOMDocument; $dom->loadHTML($html); $images = $dom->getElementsByTagName(‘img’); foreach ($images as $image) { $image->setAttribute(‘src’, ‘http://example.com/’ . $image->getAttribute(‘src’)); } $html = $dom->saveHTML();

Тем не менее, данный вариант не лишен минусов — для парсинга используется движок, в первую очередь предназначенный для работы с XML, а XML и HTML хоть и являются очень похожими языками, но всё же различаются. Из этого вытекают специфические требования к разметке: например, все HTML теги должны быть закрыты.

Simple HTML DOM

Simple HTML DOM — PHP-библиотека, позволяющая парсить HTML-код с помощью удобных jQuery-подобных селекторов.

Она лишена главного недостатка XPath — библиотека умеет работать даже с невалидным HTML-кодом, что значительно упрощает работу. Вы также забудете о проблемах с кодировкой: все преобразования выполняются автоматически.

Как и JQuery, Simple HTML DOM умеет искать и фильтровать вложенные элементы, обращаться к их атрибутам и даже выбирать отдельные логические элементы кода, например, комментарии.

В этом примере сначала подгружается, а потом модифицируется заранее заготовленный HTML-код: во второй строке происходит добавление атрибута class со значением bar первом попавшемуся элементу div, а в следующей строке мы заменяем текст элемента с id=”world” на foo.

$html = str_get_html(‘<div id=»hello»>Hello</div><div id=»world»>World</div>’); $html->find(‘div’, 1)->class = ‘bar’; $html->find(‘div’, 0)->innertext = ‘foo’; echo $html;

Несмотря на не самую высокую производительность, по сравнению с другими вариантами, Simple HTML DOM имеет самое большое русскоязычное комьюнити и наибольшую распространенность в рунете — для новичков это делает написание кода с её использованием значительно проще.

phpQuery

Как и Simple HTML DOM, phpQuery является PHP вариантом JQuery, но на этот раз более похожим на своего «старшего javascript-брата».

Портировано почти всё, что есть в JS-фреймворке: поддержка селекторов, атрибутов, манипуляций, обхода, плагинов, событий (в том числе имитации кликов и т.д.) и даже AJAX. Использовать можно как через PHP, так и через командную строку в виде отдельного приложения.

Более того, согласно нашим бенчмаркам, phpQuery оказался в 8 (!) раз быстрее Simple HTML DOM.

Вот небольшой пример на phpQuery, в котором происходит обработка заранее выбранных элементов списка (li):

foreach(pq(‘li’) as $li) { // Можно вывести различные данные обычным текстом $tagName = $li->tagName; $childNodes = $li->childNodes; // А можно добавить обертку phpQuery (аналог $() в JQuery) и, например, добавить к элементу какой-то класс pq($li)->addClass(‘my-second-new-class’); }

Подробную документацию и больше примеров найдете на официальной странице в Google Code.

htmlSQL

htmlSQL — экспериментальная PHP библиотека, позволяющая манипулировать HTML-разметкой посредством SQL-подобных запросов.

Простейший пример, извлекающий атрибуты href и title всех ссылок (элементы a) с классом list:

SELECT href,title FROM a WHERE $class == «list»

Как и с обычными mysql_ функциями, воспользовавшись методами fetch_array() или fetch_objects(), мы можем получить результат выполнения данного запроса в виде привычного ассоциативного массива или объекта.

Стоит также упомянуть о высоком быстродействии htmlSQL: часто она справляется в несколько раз быстрее phpQuery или того же Simple HTML DOM.

Тем не менее, для сложных задач вам может не хватить функциональности, а разработка библиотеки давно прекращена. Но даже несмотря на это, она всё ещё представляет интерес для веб-разработчиков: в ряде случаев значительно удобнее использовать язык SQL вместо CSS-селекторов. Особенно когда вы не знаете, что такое CSS-селекторы 😉

Вывод

В своем мини-исследовании мы пришли к выводу, что в большинстве случаев для парсинга лучше использовать библиотеку phpQuery: она быстрая, функциональная и современная.

С другой стороны, для совсем простых задач логично было бы использовать стандартные модули PHP, такие как XPath, DOM или, на крайний случай, регулярные выражения.

Что-то ещё?

Для PHP существуют ещё десятки разнообразных библиотек и инструментов для парсинга, но в этой статье мы рассмотрели только самые интересные, функциональные и производительные.

Подробнее о других способах парсинга средствами PHP можно прочитать в соответствующей теме на StackOverflow.

Если вы не используете PHP, то можете ознакомится с кратким списком похожих инструментов для других языков программирования:

Пишем парсер контента на PHP

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

Работать мы будем с CURL, но для начала давайте разберёмся, что эта аббревиатура обозначает. CURL – это программа командной строки, позволяющая нам общаться с серверами используя для этого различные протоколы, в нашем случаи HTTP и HTTPS. Для работы с CURL в PHP есть библиотека libcurl, функции которой мы и будем использовать для отправки запросов и получения ответов от сервера.

Двигаемся дальше и определяемся с нашей целью. Для примера я выбрал наверняка всем известный магазин svyaznoy. Для того, чтобы спарсить категории этого магазина, предлагаю перейти на страницу каталога:

Как можно увидеть из скриншота все категории находятся в ненумерованном списке, а подкатегории:

Внутри отельного элемента списка в таком же ненумерованном. Структура несложная, осталось только её получить. Товары мы возьмем из раздела «Все телефоны»:

На странице получается 24 товара, у каждого мы вытянем: картинку, название, ссылку на товар, характеристики и цену.

Пишем скрипт парсера

Если вы уже прочли предыдущею статью, то из неё можно было подчеркнуть, что процесс и скрипт парсинга сайта состоит из двух частей:

  1. Нужно получить HTML код страницы, которой нам необходим;
  2. Разбор полученного кода с сохранением данных и дальнейшей обработки их (как и в первой статье по парсингу мы будем использовать phpQuery, в ней же вы найдете, как установить её через composer).

Для решения первого пункта мы напишем простой класс с одним статическим методом, который будет оберткой над CURL. Так код можно будет использовать в дальнейшем и, если необходимо, модифицировать его. Первое, с чем нам нужно определиться — как будет называться класс и метод и какие будут у него обязательные параметры:

class Parser{ public static function getPage($params = ){ if($params){ if(!empty($params)){ $url = $params; // Остальной код пишем тут } } return false; } }

Основной метод, который у нас будет – это getPage() и у него всего один обязательный параметр URL страницы, которой мы будем парсить. Что ещё будет уметь наш замечательный метод, и какие значения мы будем обрабатывать в нем:

  • $useragent – нам важно иметь возможность устанавливать заголовок User-Agent, так мы сможем сделать наши обращения к серверу похожими на обращения из браузера;
  • $timeout – будет отвечать за время выполнения запроса на сервер;
  • $connecttimeout – так же важно указывать время ожидания соединения;
  • $head – если нам потребуется проверить только заголовки, которые отдаёт сервер на наш запрос этот параметр нам просто будет необходим;
  • $cookie_file – тут всё просто: файл, в который будут записывать куки нашего донора контента и при обращении передаваться;
  • $cookie_session – иногда может быть необходимо, запрещать передачу сессионных кук;
  • $proxy_ip – параметр говорящий, IP прокси-сервера, мы сегодня спарсим пару страниц, но если необходимо несколько тысяч, то без проксей никак;
  • $proxy_port – соответственно порт прокси-сервера;
  • $proxy_type – тип прокси CURLPROXY_HTTP, CURLPROXY_SOCKS4, CURLPROXY_SOCKS5, CURLPROXY_SOCKS4A или CURLPROXY_SOCKS5_HOSTNAME;
  • $headers – выше мы указали параметр, отвечающий за заголовок User-Agent, но иногда нужно передать помимо его и другие, для это нам потребуется массив заголовков;
  • $post – для отправки POST запроса.

Конечно, обрабатываемых значений много и не всё мы будем использовать для нашей сегодняшней задачи, но разобрать их стоит, так как при парсинге больше одной страницы многое выше описанное пригодится. И так добавим их в наш скрипт:

$useragent = !empty($params) ? $params : «Mozilla/5.0 (Windows NT 6.3; W…) Gecko/20100101 Firefox/57.0»; $timeout = !empty($params) ? $params : 5; $connecttimeout = !empty($params) ? $params : 5; $head = !empty($params) ? $params : false; $cookie_file = !empty($params) ? $params : false; $cookie_session = !empty($params) ? $params : false; $proxy_ip = !empty($params) ? $params : false; $proxy_port = !empty($params) ? $params : false; $proxy_type = !empty($params) ? $params : false; $headers = !empty($params) ? $params : false; $post = !empty($params) ? $params : false;

Как видите, у всех параметров есть значения по умолчанию. Двигаемся дальше и следующей строчкой напишем кусок кода, который будет очищать файл с куками при запросе:

if($cookie_file){ file_put_contents(__DIR__.»/».$cookie_file, «»); }

Так мы обезопасим себя от ситуации, когда по какой-либо причине не создался файл.

Для работы с CURL нам необходимо вначале инициализировать сеанс, а по завершению работы его закрыть, также при работе важно учесть возможные ошибки, которые наверняка появятся, а при успешном получении ответа вернуть результат, сделаем мы это таким образам:

$ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); // Далее продолжаем кодить тут curl_setopt($ch, CURLINFO_HEADER_OUT, true); $content = curl_exec($ch); $info = curl_getinfo($ch); $error = false; if($content === false){ $data = false; $error = curl_error($ch); $error = self::$error_codes; }else{ $data = $content; $data = $info; } curl_close($ch); return ;

Первое, что вы могли заметить – это статическое свойство $error_codes, к которому мы обращаемся, но при этом его ещё не описали. Это массив с расшифровкой кодов функции curl_errno(), давайте его добавим, а потом разберем, что происходит выше.

private static $error_codes = ;

После того, как мы инициализировали соединения через функцию curl_setopt(), установим несколько параметров для текущего сеанса:

  • CURLOPT_URL – первый и обязательный — это адрес, на который мы обращаемся;
  • CURLINFO_HEADER_OUT –массив с информацией о текущем соединении.

Используя функцию curl_exec(), мы осуществляем непосредственно запрос при помощи CURL, а результат сохраняем в переменную $content, по умолчанию после успешной отработки результат отобразиться на экране, а в $content упадет true. Отследить попутную информацию при запросе нам поможет функция curl_getinfo(). Также важно, если произойдет ошибка — результат общения будет false, поэтому, ниже по коду мы используем строгое равенство с учетом типов. Осталось рассмотреть ещё две функции это curl_error() – вернёт сообщение об ошибке, и curl_errno() – код ошибки. Результатом работы метода getPage() будет массив, а чтобы его увидеть давайте им воспользуемся, а для теста сделаем запрос на сервис httpbin для получения своего IP.

Кстати очень удобный сервис, позволяющий отладить обращения к серверу. Так как, например, для того что бы узнать свой IP или заголовки отправляемые через CURL, нам бы пришлось бы писать костыль. $html = Parser::getPage();

Если вывести на экран, то у вас должна быть похожая картина:

Если произойдет ошибка, то результат будет выглядеть так:

При успешном запросе мы получаем заполненную ячейку массива data с контентом и информацией о запросе, при ошибке заполняется ячейка error. Из первого скриншота вы могли заметить первую неприятность, о которой я выше писал контент сохранился не в переменную, а отрисовался на странице. Чтобы решить это, нам нужно добавить ещё один параметр сеанса CURLOPT_RETURNTRANSFER.

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

Обращаясь к страницам, мы можем обнаружить, что они осуществляют редирект на другие, чтобы получить конечный результат добавляем:

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

Теперь можно увидеть более приятную картину:

Двигаемся далее, мы описали переменные $useragent, $timeout и $connecttimeout. Добавляем их в наш скрипт:

curl_setopt($ch, CURLOPT_USERAGENT, $useragent); curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connecttimeout);

Для того, чтобы получить заголовки ответа, нам потребуется добавить следующий код:

if($head){ curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_NOBODY, true); }

Мы отключили вывод тела документа и включили вывод шапки в результате:

Для работы со ссылками с SSL сертификатом, добавляем:

if(strpos($url, «https») !== false){ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); }

Уже получается весьма неплохой скрипт парсера контента, мы добрались до кук и тут стоит отметить — частая проблема, когда они не сохраняются. Одной из основных причин может быть указание относительного пути, поэтому нам стоит это учесть и написать следующие строки:

if($cookie_file){ curl_setopt($ch, CURLOPT_COOKIEJAR, __DIR__.»/».$cookie_file); curl_setopt($ch, CURLOPT_COOKIEFILE, __DIR__.»/».$cookie_file); if($cookie_session){ curl_setopt($ch, CURLOPT_COOKIESESSION, true); } }

Предлагаю проверить, а для этого я попробую вытянуть куки со своего сайта:

Всё получилось, двигаемся дальше и нам осталось добавить в параметры сеанса: прокси, заголовки и возможность отправки запросов POST:

if($proxy_ip && $proxy_port && $proxy_type){ curl_setopt($ch, CURLOPT_PROXY, $proxy_ip.»:».$proxy_port); curl_setopt($ch, CURLOPT_PROXYTYPE, $proxy_type); } if($headers){ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); } if($post){ curl_setopt($ch, CURLOPT_POSTFIELDS, $post); }

Это малая доля параметров, с которыми можно работать, все остальные находятся в официальной документации PHP. Вот мы завершили с нашей оберткой, и пришло время, что-нибудь спарсить!

Парсим категории и товары с сайта

Теперь, при помощи нашего класса Parser, мы можем сделать запрос и получить страницу с контентом. Давайте и поступим:

$html = Parser::getPage();

Следующим шагом разбираем пришедший ответ и сохраняем название и ссылку категории в результирующий массив:

if(!empty($html)){ $content = $html; phpQuery::newDocument($content); $categories = pq(«.b-category-menu»)->find(«.b-category-menu__link»); $tmp = ; foreach($categories as $key => $category){ $category = pq($category); $tmp = ; $submenu = $category->next(«.b-category-submenu»)->find(«.b-category-submenu__link»); foreach($submenu as $submen){ $submen = pq($submen); $tmp = ; } } phpQuery::unloadDocuments(); }

Чуть более подробно работу с phpQuery я разобрал в первой статье по парсингу контента. Если вкратце, то мы пробегаемся по DOM дереву и вытягиваем нужные нам данные, их я решил протримить, чтобы убрать лишние пробелы. А теперь выведем категории на экран:

<ul> <?php foreach($tmp as $value): ?> <li> <a href=»https://www.svyaznoy.ru<?php echo($value); ?>» target=»_blank»> <?php echo($value); ?> </a> <ul> <? if(!empty($value)): ?> <?php foreach($value as $val): ?> <li> <a href=»https://www.svyaznoy.ru<?php echo($val); ?>» target=»_blank»> <?php echo($val); ?> </a> </li> <?php endforeach; ?> <? endif; ?> </ul> </li> <?php endforeach; ?> </ul>

В результате мы получили все ссылки на категории. Для получения товаров используем тот же принцип:

$html = Parser::getPage();

Получаем страницу, тут я увеличил время соединения, так как 5 секунд не хватило, и разбираем её, парся необходимый контент:

if(!empty($html)){ $content = $html; phpQuery::newDocument($content); $products = pq(«.b-listing__generated-container»)->find(«.b-product-block .b-product-block__content»); $tmp = ; foreach($products as $key => $product){ $product = pq($product); $tmp = ; $chars = $product->find(«.b-product-block__info .b-product-block__tech-chars li»); foreach($chars as $char){ $tmp = pq($char)->text(); } } phpQuery::unloadDocuments(); }

Теперь проверим, что у нас получилось, и выведем на экран:

<div class=»tovars»> <?php foreach($tmp as $value): ?> <a href=»https://www.svyaznoy.ru<?php echo($value); ?>» target=»_blank» class=»tovar»> <img src=»<?php echo($value); ?>» alt=»<?php echo($value); ?>» /> <span class=»name»> <?php echo($value); ?> </span> <span class=»price»> <?php echo($value); ?> </span> <ul class=»chars»> <? if(!empty($value)): ?> <?php foreach($value as $val): ?> <li> <?php echo($val); ?> </li> <?php endforeach; ?> <? endif; ?> </ul> </a> <?php endforeach; ?> </div>

Вот мы и написали парсер контента PHP, как видите, нет нечего сложного, при помощи этого скрипта можно легко спарсить страницы любого сайта, но перед тем, как заканчивать статью, хотелось пояснить некоторые моменты. Во-первых, если вы хотите парсить более одной страницы, то не стоит забывать, что сам процесс парсинга ресурса затратная операция, поэтому в идеале лучше, чтобы скрипт был вынесен на отдельный сервер, где и будет запускаться по крону. Ещё один момент — к каждому донору стоит подходить индивидуально, так как, во-первых: у них разный HTML код и он, с течением времени, может меняться, во-вторых: могут быть различные защиты от парсинга и проверки, поэтому для подбора необходимого набора заголовков и параметров может потребоваться отладочный прокси (я пользуюсь Fiddler). И последние, что я добавлю — используйте для парсинга прокси и чем больше, тем лучше, так как, когда на сервер донора полетят тысячи запросов, то неизбежно IP, с которого осуществляется обращение будет забанен, поэтому стоит прогонять свои запросы через прокси-сервера.

Полный пример с библеотекай phpQuery вы найдете на github.

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

Ваш e-mail не будет опубликован. Обязательные поля помечены *