Наша совместная команда Banwar.org

Связаться с нами

  • (097) ?601-88-87
    (067) ?493-44-27
    (096) ?830-00-01

Статьи

PHP парсер без регулярних виразів

Основою парсеров HTML сайтів є дві функції: підготовка запитів до сервера і розбір відповіді за допомогою регулярних виразів. Але що робити, наприклад, у випадках, коли потрібно по-швидкому щось Спарс, а розбиратися з премудростями роботи з регулярними виразами лінь? У таких випадках нам допоможуть спеціальні PHP бібліотеки для роботи на сервері з HTML структурами даних, також як на jQuery.

Для цих цілей більше 10-ка різних бібліотек написано PHP HTML DOM, phpQuery, QueryPath, XPath. Ще є варіанти, вбудовані в різні PHP фреймворки.

Я для даної статті вибрав phpQuery парсер для використання jQuery подібних селектор. У застосуванні даної бібліотеки немає нічого складного, якщо ви маєте досвід роботи з javascript бібліотекою jQuery або її аналогами.

За основу взяв парсер ціни товару з першій статті про розробку парсеров , Щоб можна було наочно порівняти різні підходи до вирішення однієї задачі.

Відразу покажу код файлу index.php:

<? 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 ( "dmYHis", time ()); / * --- 1.1 --- переобумовленої змінні на основі GET або POST параметрів * / if (isset ($ _ REQUEST [ 'gearbest_url'])) $ gearbest_url = trim ($ _ REQUEST [ 'gearbest_url']); if (isset ($ _ REQUEST [ 'action'])) $ action = $ _REQUEST [ 'action']; / * --- 1.2 --- Запити за допомогою cURL * / / * --- 1.2.1 --- Завантаження сторінки за допомогою 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 [ 'html'] = curl_exec ($ ch); $ Info = curl_getinfo ($ ch); if ($ info [ 'http_code']! = 200 && $ info [ 'http_code']! = 404) {$ error_page [] = array (1, $ page_url, $ info [ 'http_code']); if ($ retry) {sleep ($ pause_time); $ Response [ 'html'] = curl_exec ($ ch); $ Info = curl_getinfo ($ ch); if ($ info [ 'http_code']! = 200 && $ info [ 'http_code']! = 404) $ error_page [] = array (2, $ page_url, $ info [ 'http_code']); }} $ Response [ 'code'] = $ info [ 'http_code']; $ Response [ 'errors'] = $ error_page; curl_close ($ ch); return $ response; } / * --- 1.3 --- Функції для Gearbest.com * / / * --- 1.3.1 --- Парсинг ціни товару * / function get_gearbest_price ($ gearbest_url) {/ * $ gearbest_url - адреса сторінки товару на Gearbest * / $ res_arr = array (); $ Res_arr [ 'price_list'] = array (); $ Base_url = "https://www.gearbest.com"; $ Response_arr = curl_get_contents ($ gearbest_url, $ base_url, 5, 1); $ Page = $ response_arr [ 'html']; $ Page_code = $ response_arr [ 'code']; $ Res_arr [ 'error_page'] = $ response_arr [ 'errors']; //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); } Require_once ( '/ phpQuery / phpQuery.php'); $ Doc = phpQuery :: newDocumentHTML ($ page); phpQuery :: selectDocument ($ doc); $ Res_arr [ 'price_list'] [ 'price'] = pq ( '# unit_price') -> attr ( 'data-orgp'); $ Res_arr [ 'price_list'] [ 'currency'] = pq ( '. Switcher-currency-c span a') -> attr ( 'data-bizhong'); $ Res_arr [ 'error'] = ''; } Else {$ res_arr [ 'price'] = 0; $ Res_arr [ 'currency'] = 'nodata'; $ Res_arr [ 'error'] [] = 'Помилка завантаження сторінки'; } Return $ res_arr; } / * --- 1.4 --- Висновок даних в HTML * / / * --- 1.4.1 --- Висновок інформації про спарсенних фото * / function price_list_html ($ price_list) {echo '<p> Ціна:'. $ Price_list [ 'price']. '<Span class = \ "currency \">'. $ Price_list [ 'currency']. '</ Span> </ p>'; } / * --- 1.4.2 --- Висновок помилок * / function error_list_html ($ errors) {if (! Empty ($ errors)) {echo "<p> Під час роботи парсера відбулися наступні помилки: </ p> \ n "; echo "<ul> \ n"; foreach ($ errors 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 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); $ Res_arr = get_gearbest_price ($ gearbest_url); } Else {$ res_arr [ 'errors'] [] = "Неможливо задано адресу сторінки товару"; }} / * --- 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 [type = "text"] {font-size: 1em; min-height: 36px; box-sizing: border-box; } Input [type = "submit"], input [type = "button"] {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 [type = "submit"]: hover, input [type = "button"]: 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 ($ res_arr [ 'price_list'])) {price_list_html ($ res_arr [ 'price_list']); }?&gt; </ Div> <div class = "errors_block"> <? Php error_list_html ($ res_arr [ 'errors']); run_time_html ($ time_start); ?> </ Div> <div class = "copyright"> & copy Ідея і реалізація - <a href = "https://seorubl.ru/" target = "_ blank" title = "Записки Заповзятливого Людини" rel = "generator" > ПЧ </a> // 01.05.2017 р. </ div> </ div> </ body> </ html>

Основні зміни були зроблені в функції get_gearbest_price (), з неї пропали регулярні вирази. Замість них підключається бібліотека phpQuery і Парс потрібні дані з атрибутів. Елементи HTML вибираються за значенням класів і id.

require_once ( '/ phpQuery / phpQuery.php'); $ Doc = phpQuery :: newDocumentHTML ($ page); phpQuery :: selectDocument ($ doc); $ Res_arr [ 'price_list'] [ 'price'] = pq ( '# unit_price') -> attr ( 'data-orgp'); $ Res_arr [ 'price_list'] [ 'currency'] = pq ( '. Switcher-currency-c span a') -> attr ( 'data-bizhong');

Дуже схоже на принципи роботи з DOM об'єктами в jQuery.

В результаті вийшов цілком робочий парсер цін без використання регулярних виразів.

Звичайно, всередині бібліотеки phpQuery активно пріменіются регулярні вирази для розбору DOM структури документа, але від нас ця магія прихована.

У парсером з прикладу я використав власну функцію curl_get_contents () для запитів до сервера і отримання від нього відповідей. У phpQuery і її аналогах є готові функції для скачування HTML сторінок. Але вони не завжди застосовні для цілей парсинга сайтів, так як використовують стандартну функцію PHP get_file_contents ().

З плюсів застосування для розробки парсеров на основі phpQuery можна виділити простоту роботи і широкий функціонал вибірки по селекторам і атрибутам. Підтримка різних структур даних: XML, HTML, xHTML.

Мінуси характерні:

  • використання в проекті додаткової сторонньої бібліотеки (наприклад phpQuery зупинилася в розвитку в 2009 році),
  • досить великоваговий скрипт (близько 1 мб),
  • для цілей парсинга використовується мала частина доступного функціоналу.

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

Але як варіант, при необхідності швидко зробити парсер зі складною обробкою DOM або XML структури даних, цілком виправдано застосувати яку-небудь PHP jQuery подібну бібліотеку. Треба тільки обов'язково протестувати швидкість роботи створеного скрипта і стабільність при некоректних вхідних даних.

PHP парсер без регулярних виразів

5 (100%) 1 vote [s]

Чи не жмісь! З друзями посиланням поділися:

Цікаве по темі

Але що робити, наприклад, у випадках, коли потрібно по-швидкому щось Спарс, а розбиратися з премудростями роботи з регулярними виразами лінь?
Php if (! empty ($ gearbest_url)) echo $ gearbest_url;?
Php if ($ action &&! empty ($ res_arr [ 'price_list'])) {price_list_html ($ res_arr [ 'price_list']); }?
Gt; </ Div> <div class = "errors_block"> <?
Php error_list_html ($ res_arr [ 'errors']); run_time_html ($ time_start); ?

Новости

Banwar.org
Наша совместная команда Banwar.org. Сайт казино "Пари Матч" теперь доступен для всех желающих, жаждущих волнения и азартных приключений.