Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Парсер-регулярка
Форумы портала PHP.SU » PHP » Регулярные выражения » Парсер-регулярка

Страниц (1): [1]
 

1. Electron - 03 Октября, 2014 - 17:24:18 - перейти к сообщению
Доброго времени суток! Помогите, пожалуйста, с написанием регулярного выражения для парсера, не силён я в них... Суть в том, что я с помощью cURL получаю данные со стороннего сайта, нужно написать регуляку, которая из следующего кода помогла бы вытащить данные, выделенные капсом, в массив, при том что все виды описания отдельно друг от друга. Количество элементов списка может быть сколько угодно. Для разбивки, думаю, можно как-то использовать наименования стилей и комментарии между элементами списка, но не уверен как. Спасибо за любую помощь!

CODE (html):
скопировать код в буфер обмена
  1. {много_кода}
  2. <ul class="list -inline good">
  3. <!-- -->
  4. <li class="list__item">
  5.         <div class="list__title">НАЗВАНИЕ</div>
  6.         <div class="list__image">
  7.                 <a href="ССЫЛКА" class="list__link">
  8.                         <img src="ССЫЛКА" alt="">
  9.                         <span class="list__description">ОПИСАНИЕ1, ОПИСАНИЕ2, ОПИСАНИЕ3</span>
  10.                 </a>
  11.         </div>
  12.         <div class="list__price">ЦЕНА</div>
  13. </li>
  14. <!-- -->
  15. <li class="list__item">
  16.         <div class="list__title">НАЗВАНИЕ</div>
  17.         <div class="list__image">
  18.                 <a href="ССЫЛКА" class="list__link">
  19.                         <img src="ССЫЛКА" alt="">
  20.                         <span class="list__description">ОПИСАНИЕ1, ОПИСАНИЕ2, ОПИСАНИЕ3</span>
  21.                 </a>
  22.         </div>
  23.         <div class="list__price">ЦЕНА</div>
  24. </li>
  25. <!-- -->
  26. </ul>
  27. {много_кода}
2. jehaby - 04 Октября, 2014 - 01:04:31 - перейти к сообщению
Привет. Можно сделать так, без регулярок:

PHP:
скопировать код в буфер обмена
  1. <?PHP
  2.  
  3. $xpath = new DOMXPath(DOMDocument :: loadHTMLFile('path_to_fille.html'));
  4.  
  5. $query = "//ul/li[@class='list__item']";
  6.  
  7. foreach ($xpath->query($query) as $node) {
  8.     $res['title'] = $xpath->query("div[@class='list__title']", $node)->item(0)->textContent;
  9.     $res['description'] = $xpath->query("div/a/span[@class='list__description']", $node)->item(0)->textContent;
  10.     $res['price'] = $xpath->query("div[@class='list__price']", $node)->item(0)->textContent;
  11.     $data[] = $res;
  12. }
  13. }
3. Electron - 06 Октября, 2014 - 11:01:34 - перейти к сообщению
jehaby пишет:
Привет. Можно сделать так, без регулярок:

PHP:
скопировать код в буфер обмена
  1. <?PHP
  2.  
  3. $xpath = new DOMXPath(DOMDocument :: loadHTMLFile('path_to_fille.html'));
  4.  
  5. $query = "//ul/li[@class='list__item']";
  6.  
  7. foreach ($xpath->query($query) as $node) {
  8.     $res['title'] = $xpath->query("div[@class='list__title']", $node)->item(0)->textContent;
  9.     $res['description'] = $xpath->query("div/a/span[@class='list__description']", $node)->item(0)->textContent;
  10.     $res['price'] = $xpath->query("div[@class='list__price']", $node)->item(0)->textContent;
  11.     $data[] = $res;
  12. }
  13. }

Батеньки! Надо же, массив получаю! jehaby, спасибо!

Правда кодировка битая, как можно решить проблему на стороне получения?

В общем на исходном сайте кодировка в Windows-1251, на получаемом в UTF-8, после заноса данных в массив пытаюсь поменять кодировку элементов функцией iconv, но она с одной кракозябры меняется на другую. Но как поменять кодировку до заноса в массив? Пробовал так (но ничего не изменилось):
PHP:
скопировать код в буфер обмена
  1. $doc  = new DOMDocument('4.0', 'UTF-8');
  2. $doc->loadHTMLFile($link);
  3. $doc->encoding = 'UTF-8';
  4. $xpath = new DOMXpath($doc);


И ещё я не получаю ссылок, правильно делаю?
PHP:
скопировать код в буфер обмена
  1. $res['link'] = $xpath->query("div/a[@class='list__link']", $node)->item(0)->textContent;
  2. $res['image'] = $xpath->query("div/a/img[@class='list__image']", $node)->item(0)->textContent;

С последним разобрался:
PHP:
скопировать код в буфер обмена
  1. $res['link'] = $xpath->query("div/a[@class='list__link']/@href", $node)->item(0)->textContent;
  2. $res['image'] = $xpath->query("div[@class='list__image']/a/img/@src", $node)->item(0)->textContent;
4. jehaby - 06 Октября, 2014 - 20:26:17 - перейти к сообщению
Если исходный файл в 1251, то можно и отдавать в 1251, добавив

PHP:
скопировать код в буфер обмена
  1.  
  2. header('Content-Type: text/html; charset=windows-1251');
  3.  


и обернув каждый запрос к xpath utf8_decode, вот так:
PHP:
скопировать код в буфер обмена
  1.  
  2.  $res['price'] = utf8_decode($xpath->query("div[@class='list__price']", $node)->item(0)->textContent);
  3.  


Как красиво преобразовать и отдавать в UTF8 пока не подскажу, но думаю что за полчаса гугления разобраться с этим вполне реально. Самому было бы интересно глянуть на решение.
5. Electron - 07 Октября, 2014 - 09:51:08 - перейти к сообщению
jehaby пишет:
Если исходный файл в 1251, то можно и отдавать в 1251, добавив

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

jehaby пишет:
и обернув каждый запрос к xpath utf8_decode, вот так:

Как красиво преобразовать и отдавать в UTF8 пока не подскажу, но думаю что за полчаса гугления разобраться с этим вполне реально. Самому было бы интересно глянуть на решение.

К сожалению данная запись превратила надпись "руб" из "ðóá" в "���". А функция utf8_encode в "ðóá". Функция iconv (win1251 => utf8) в "ðóá".

Что же касается отсеивания лишней информации, и разделения описания, то (может кому пригодится):

PHP:
скопировать код в буфер обмена
  1. foreach($data as $key => $val) {
  2.         if($val["link"] == "") {
  3.                 unset($data[$key]);
  4.         } else {
  5.                 $data[$key]["description"] = trim(explode(",", $val["description"]));   // правда функция trim не отрабатывает...
  6.         }
  7. }
6. jehaby - 07 Октября, 2014 - 21:03:46 - перейти к сообщению
Хм, вроде работает, если конвертировать файл из cp1251 в utf8 перед дем как скормить его DOMDocument.

PHP:
скопировать код в буфер обмена
  1.  
  2. $source = mb_convert_encoding(file_get_contents($file), 'UTF-8', 'Windows-1251');
  3. $xpath = new DOMXPath(DOMDocument :: loadHTML($source));
  4.  
7. Electron - 08 Октября, 2014 - 17:40:45 - перейти к сообщению
jehaby пишет:
Хм, вроде работает, если конвертировать файл из cp1251 в utf8 перед дем как скормить его DOMDocument.

И правда работает! Спасибо! Осталось только, для полного фэншуя, удалить символы переноса строк в массиве (с которыми не справилась функция trim), но не критично, и так всё отлично работает, шик! Улыбка
8. jehaby - 09 Октября, 2014 - 18:27:43 - перейти к сообщению
Цитата:
удалить символы переноса строк в массиве


Это элементарно делается с помощью str_replace или preg_replace.
9. Electron - 23 Октября, 2014 - 11:51:48 - перейти к сообщению
jehaby пишет:
Это элементарно делается с помощью str_replace или preg_replace.

Ага, сделал. Спасибо за помощь!

А не подскажешь как разделить цены в таком случае?
PHP:
скопировать код в буфер обмена
  1. <div class="list__price">
  2.         <s>300 руб.</s>
  3.         500 руб.
  4. </div>

К первой цене так "div[@class='list__price']/s", к обоим так "div[@class='list__price']", а к второй цене как добраться?

Сделал регуляркой (хотя было бы лучше разделить на уровне вытягивания данных):
PHP:
скопировать код в буфер обмена
  1. <? preg_match_all("|руб.(.*)|is", $val["price"], $result, PREG_SET_ORDER); ?>
10. Electron - 24 Октября, 2014 - 09:53:13 - перейти к сообщению
Ещё один вопрос возник, не подскажешь? Как сделать прокрутку внутри прокрутки, т.е. на выходе получить многомерный массив? В одном массиве должен получиться массив с ссылками на разные изображения одного элемента. Ну по типу:
PHP:
скопировать код в буфер обмена
  1. foreach($xpath->query($query) as $node) {
  2.         $res['price'] = $xpath->query("div[@class='row']", $node)->item(0)->textContent;
  3.         $res['title'] = $xpath->query("div[@class='row']/h1", $node)->item(0)->textContent;
  4.         foreach($xpath->query($query) as $node) {
  5.                 $res['gallery'] = $xpath->query("div[@class='gallery']/ul/li", $node)->item(0)->textContent;
  6.                 $data[] = $res;
  7.         }
  8.         $data[] = $res;
  9. }
11. Electron - 10 Ноября, 2014 - 09:21:24 - перейти к сообщению
Сделал как-то криво, но работает, наверное можно куда красивее это сделать, внутри того цикла сделал новый:
PHP:
скопировать код в буфер обмена
  1. foreach($xpath->query("//div/div/table/tbody/tr") as $node) {
  2.         $res['copmlete'][] = $xpath->query("td", $node)->item(0)->textContent;
  3.         $res['copmlete'][] = $xpath->query("td", $node)->item(1)->textContent;
  4.         $res['copmlete'][] = $xpath->query("td", $node)->item(2)->textContent;
  5.         $res['copmlete'][] = $xpath->query("td", $node)->item(3)->textContent;
  6. }

 

Powered by ExBB FM 1.0 RC1