Все о парсинге RSS лент средствами PHP

Рубрика: Новости -> Скрипты -> php
Среда, 30 сентября 2009 г.
Просмотров: 7776
Подписаться на комментарии по RSS

RSS — семейство XML-форматов, предназначенных для

описания лент новостей, анонсов статей, изменений в блогах и т. п.

Информация из различных источников, представленная в формате RSS, может

быть собрана, обработана и представлена

пользователю в удобном для него

виде специальными программами-агрегаторами.

То есть это по сути XML (кто незнает что это идем в википедию и читаем),

а XML как нам известно хорошо структурированный документ. Я клоню к

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

(например: <title>Заголовок</title>), иначе это не RSS.

Думаю на данном этапе суть ясна: нам нужно получить информацию

заключенную между тегами. Любая RSS лента имеет заголовок заключенный

между тегами <title></title> и сам текст статьи заключенный

между тегами < description></description>, именно их нам и

нужно спарсить.

Теперь расскажу о способах написания RSS парсера и что предлагает нам PHP для реализации.

Способ 1 – SimpleXML

SimpleXML – это расширение для PHP5 устанавливаемое

в него по умолчанию, представляет самый простой и элегантный способ

обработки XML (соответственно и RSS) файлов. Это и наиболее

предпочтительный способ, но он стал доступным только в 5 версии PHP.

Тут нет ничего проще, данный код наглядно показывает как просто парсить

RSS ленты средствами SimpleXML:

<code><span class="pun"><?</span><span class="pln">
$url </span><span class="pun">=</span><span class="pln"> </span><span class="str">'rss.xml'</span><span class="pun">;</span><span class="pln">       </span><span class="com">//адрес RSS ленты</span><span class="pln">
$rss </span><span class="pun">=</span><span class="pln"> simplexml_load_file</span><span class="pun">(</span><span class="pln">$url</span><span class="pun">);</span><span class="pln">       </span><span class="com">//Интерпретирует XML-файл в объект</span><span class="pln">
</span><span class="com">//цикл для обхода всей RSS ленты</span><span class="pln">
</span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$rss</span><span class="pun">-></span><span class="pln">channel</span><span class="pun">-></span><span class="pln">item </span><span class="kwd">as</span><span class="pln"> $item</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        echo </span><span class="str">'<h1>'</span><span class="pun">.</span><span class="pln">$item</span><span class="pun">-></span><span class="pln">title.</span><span class="str">'</h1>'</span><span class="pun">;</span><span class="pln">       </span><span class="com">//выводим на печать заголовок статьи </span><span class="pln">
        echo $item</span><span class="pun">-></span><span class="pln">description</span><span class="pun">;</span><span class="pln">        </span><span class="com">//выводим на печать текст статьи</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">?></span></code>

Данный код выведет заголовки и тексты статей из RSS ленты. Просто

ведь? Этим SimpleXML и привлекает. Дальше вам нужно будет только

правильно распорядиться полученными данными, записать в базу или еще

куда-нибудь.

Способ 2 – XML Parser Functions

XML Parser Functions - это стандартные функции PHP

для работы с XML доступные начиная c 4-ой версии PHP. Тоже нет ничего

сложного, правда в отличие от SimpleXML совсем не элегантно.

Продемонстрирую пример:

<code><span class="pun"><?</span><span class="pln">
$url </span><span class="pun">=</span><span class="pln"> </span><span class="str">'rss.xml'</span><span class="pun">;</span><span class="pln">       </span><span class="com">//адрес RSS ленты</span><span class="pln">
$xml </span><span class="pun">=</span><span class="pln"> xml_parser_create</span><span class="pun">();</span><span class="pln">     </span><span class="com">//создаёт XML-разборщик</span><span class="pln">
xml_parser_set_option</span><span class="pun">(</span><span class="pln">$xml</span><span class="pun">,</span><span class="pln"> XML_OPTION_SKIP_WHITE</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">  </span><span class="com">//устанавливает опции XML-разборщика</span><span class="pln">
xml_parse_into_struct</span><span class="pun">(</span><span class="pln">$xml</span><span class="pun">,</span><span class="pln"> file_get_contents</span><span class="pun">(</span><span class="pln">$url</span><span class="pun">),</span><span class="pln"> $element</span><span class="pun">,</span><span class="pln"> $index</span><span class="pun">);</span><span class="pln"> </span><span class="com">//разбирает XML-данные в структуру массива</span><span class="pln">
xml_parser_free</span><span class="pun">(</span><span class="pln">$xml</span><span class="pun">);</span><span class="pln">  </span><span class="com">//освобождает XML-разборщик</span><span class="pln">
$count </span><span class="pun">=</span><span class="pln"> count</span><span class="pun">(</span><span class="pln">$index</span><span class="pun">[</span><span class="str">"TITLE"</span><span class="pun">])-</span><span class="lit">1</span><span class="pun">;</span><span class="pln">      </span><span class="com">//число проходов цикла.</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$i</span><span class="pun">=</span><span class="lit">0</span><span class="pun">;</span><span class="pln"> $i </span><span class="pun"><</span><span class="pln"> $count</span><span class="pun">;</span><span class="pln"> $i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        echo </span><span class="str">'<h1>'</span><span class="pun">.</span><span class="pln">$element</span><span class="pun">[</span><span class="pln">$index</span><span class="pun">[</span><span class="str">"TITLE"</span><span class="pun">][</span><span class="pln">$i</span><span class="pun">+</span><span class="lit">1</span><span class="pun">]][</span><span class="str">"value"</span><span class="pun">]</span><span class="pln">.</span><span class="str">'</h1>'</span><span class="pun">;</span><span class="pln">           </span><span class="com">//выводим на печать заголовок статьи </span><span class="pln">
        echo $element</span><span class="pun">[</span><span class="pln">$index</span><span class="pun">[</span><span class="str">"DESCRIPTION"</span><span class="pun">][</span><span class="pln">$i</span><span class="pun">+</span><span class="lit">1</span><span class="pun">]][</span><span class="str">"value"</span><span class="pun">];</span><span class="pln">            </span><span class="com">//выводим на печать текст статьи</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">?></span></code>

Вот таким образом мы получаем интересующие нас содержимое элементов

RSS. Но тут уже нужно разобраться с массивами которые создает XML

разборщик.

Способ 3 – Написать RSS парсер самому

Например я делал именно так, когда не знал про существование

SimpleXML и XML Parser Functions. Приведу небольшой пример парсинга RSS

обычным процедурным PHP кодом, тут за парсинг отвечает функция

preg_match_all(), которая выполняет глобальный поиск шаблона в строке.

Данный пример не совершенен и парсит только титлы и дескрипшены у RSS:

<code><span class="pun"><?</span><span class="pln">
$url </span><span class="pun">=</span><span class="pln"> </span><span class="str">'rss.xml'</span><span class="pun">;</span><span class="pln">       </span><span class="com">//адрес RSS ленты</span><span class="pln">
$rss </span><span class="pun">=</span><span class="pln"> @file_get_contents</span><span class="pun">(</span><span class="pln">$url</span><span class="pun">);</span><span class="pln">        </span><span class="com">//получаем содержимое RSS лент в виде одной строки</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$rss</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">     
        preg_match_all</span><span class="pun">(</span><span class="str">"/title>[^>]+>/"</span><span class="pun">,</span><span class="pln"> $rss</span><span class="pun">,</span><span class="pln"> $title</span><span class="pun">);</span><span class="pln">         </span><span class="com">//парсим титлы</span><span class="pln">
        preg_match_all</span><span class="pun">(</span><span class="str">"/<description>[^<]+<\/description>/"</span><span class="pun">,</span><span class="pln"> $rss</span><span class="pun">,</span><span class="pln"> $description</span><span class="pun">);</span><span class="pln">              </span><span class="com">//парсим дескрипшены</span><span class="pln">
        
        $count </span><span class="pun">=</span><span class="pln"> count</span><span class="pun">(</span><span class="pln">$title</span><span class="pun">[</span><span class="lit">0</span><span class="pun">])-</span><span class="lit">1</span><span class="pun">;</span><span class="pln">    </span><span class="com">//число проходов цикла.</span><span class="pln">
        
        </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$i</span><span class="pun">=</span><span class="lit">0</span><span class="pun">;</span><span class="pln"> $i </span><span class="pun"><</span><span class="pln"> $count</span><span class="pun">;</span><span class="pln"> $i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                echo </span><span class="str">'<h1>'</span><span class="pun">.</span><span class="pln">substr</span><span class="pun">(</span><span class="pln">$title</span><span class="pun">[</span><span class="lit">0</span><span class="pun">][</span><span class="pln">$i</span><span class="pun">+</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> </span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">8</span><span class="pun">)</span><span class="pln">.</span><span class="str">'</h1>'</span><span class="pun">;</span><span class="pln">             </span><span class="com">//выводим на печать заголовок статьи </span><span class="pln">
                echo substr</span><span class="pun">(</span><span class="pln">$description</span><span class="pun">[</span><span class="lit">0</span><span class="pun">][</span><span class="pln">$i</span><span class="pun">],</span><span class="pln"> </span><span class="lit">13</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">14</span><span class="pun">);</span><span class="pln">              </span><span class="com">//выводим на печать текст статьи</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        echo </span><span class="str">'<font color="red">Ошибка парсинга '</span><span class="pun">.</span><span class="pln">$url.</span><span class="str">'</font>'</span><span class="pun">;</span><span class="pln">       </span><span class="com">//выводим ошибку если file_get_contents() вернула false</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">?></span></code>

Таким же способом можно и отпарсить остальные элементы RSS ленты, главное написать правильно регулярку.

На этих трех способах мы и остановимся, еще есть наверняка множество

сторонних скриптов и классов в PHP для парсинга XML, например magpieRSS

у которого проблемы с кодировкой при парсинге и решить ее у меня не

получилось, да собственно не очень то и хотелось, когда есть SimpleXML

и XML Parser Functions. Вот кстати о проблемах с кодировкой мы сейчас и

поговорим…

Проблемы с кодировкой

RSS ленты как правило находятся в кодировке UTF-8, при парсинге

русского текста тремя способами описанными выше, нам на экран выводятся

кракозябры. Все потому, что тест к нам приходит в кодировке UTF-8. Для

того что бы вывести нормальные РУССКИЕ буквы нужно перекодировать

спарсеный текст из кодировки UTF-8 в Windows-1251. Для этих целей в PHP

существует функция iconv(),

но она доступна не на всех серверах и чтобы избежать дальнейших проблем

с вашим RSS парсером советую использовать самописную функцию

перекодировки. Вникать в тонкости кодировок и разбираться как из одной

кодировки получается другая думаю вам не хочется, так же не хотелось и

мне. Немного погуглив я нашел замечательную функцию перекодировки из UTF-8 в Windows-1251 и обратно,

предоставляет ее некий товарищ E64F. Возможно конечно он тоже ее где-то

слямзил, но это не так важно, важно то что она мне очень понравилась по

сравнению с другими нагуглеными функциями. Выкладываю функцию и пример

ее использования:

<code><span class="pun"><?</span><span class="pln">
echo utf8_convert</span><span class="pun">(</span><span class="pln">$str</span><span class="pun">,</span><span class="pln"> </span><span class="str">"w"</span><span class="pun">);</span><span class="pln">   </span><span class="com">//перекодирует $str из UTF-8 в Windows-1251 и выведет на экран</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> utf8_convert</span><span class="pun">(</span><span class="pln">$str</span><span class="pun">,</span><span class="pln"> $type</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">static</span><span class="pln"> $conv </span><span class="pun">=</span><span class="pln"> </span><span class="str">''</span><span class="pun">;</span><span class="pln">
   </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">is_array</span><span class="pun">(</span><span class="pln">$conv</span><span class="pun">))</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
      $conv </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">();</span><span class="pln">
      </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$x</span><span class="pun">=</span><span class="lit">128</span><span class="pun">;</span><span class="pln"> $x </span><span class="pun"><=</span><span class="pln"> </span><span class="lit">143</span><span class="pun">;</span><span class="pln"> $x</span><span class="pun">++)</span><span class="pln">
      </span><span class="pun">{</span><span class="pln">
         $conv</span><span class="pun">[</span><span class="str">'utf'</span><span class="pun">][]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> chr</span><span class="pun">(</span><span class="lit">209</span><span class="pun">)</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> chr</span><span class="pun">(</span><span class="pln">$x</span><span class="pun">);</span><span class="pln">
         $conv</span><span class="pun">[</span><span class="str">'win'</span><span class="pun">][]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> chr</span><span class="pun">(</span><span class="pln">$x </span><span class="pun">+</span><span class="pln"> </span><span class="lit">112</span><span class="pun">);</span><span class="pln">
      </span><span class="pun">}</span><span class="pln">
      </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$x</span><span class="pun">=</span><span class="lit">144</span><span class="pun">;</span><span class="pln"> $x</span><span class="pun"><=</span><span class="pln"> </span><span class="lit">191</span><span class="pun">;</span><span class="pln"> $x</span><span class="pun">++)</span><span class="pln">
      </span><span class="pun">{</span><span class="pln">
         $conv</span><span class="pun">[</span><span class="str">'utf'</span><span class="pun">][]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> chr</span><span class="pun">(</span><span class="lit">208</span><span class="pun">)</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> chr</span><span class="pun">(</span><span class="pln">$x</span><span class="pun">);</span><span class="pln">
         $conv</span><span class="pun">[</span><span class="str">'win'</span><span class="pun">][]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> chr</span><span class="pun">(</span><span class="pln">$x </span><span class="pun">+</span><span class="pln"> </span><span class="lit">48</span><span class="pun">);</span><span class="pln">
      </span><span class="pun">}</span><span class="pln">
      $conv</span><span class="pun">[</span><span class="str">'utf'</span><span class="pun">][]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> chr</span><span class="pun">(</span><span class="lit">208</span><span class="pun">)</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> chr</span><span class="pun">(</span><span class="lit">129</span><span class="pun">);</span><span class="pln">
      $conv</span><span class="pun">[</span><span class="str">'win'</span><span class="pun">][]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> chr</span><span class="pun">(</span><span class="lit">168</span><span class="pun">);</span><span class="pln">
      $conv</span><span class="pun">[</span><span class="str">'utf'</span><span class="pun">][]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> chr</span><span class="pun">(</span><span class="lit">209</span><span class="pun">)</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> chr</span><span class="pun">(</span><span class="lit">145</span><span class="pun">);</span><span class="pln">
      $conv</span><span class="pun">[</span><span class="str">'win'</span><span class="pun">][]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> chr</span><span class="pun">(</span><span class="lit">184</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
   </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$type </span><span class="pun">==</span><span class="pln"> </span><span class="str">'w'</span><span class="pun">)</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
      </span><span class="kwd">return</span><span class="pln"> str_replace</span><span class="pun">(</span><span class="pln">$conv</span><span class="pun">[</span><span class="str">'utf'</span><span class="pun">],</span><span class="pln"> $conv</span><span class="pun">[</span><span class="str">'win'</span><span class="pun">],</span><span class="pln"> $str</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
   elseif </span><span class="pun">(</span><span class="pln">$type </span><span class="pun">==</span><span class="pln"> </span><span class="str">'u'</span><span class="pun">)</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
      </span><span class="kwd">return</span><span class="pln"> str_replace</span><span class="pun">(</span><span class="pln">$conv</span><span class="pun">[</span><span class="str">'win'</span><span class="pun">],</span><span class="pln"> $conv</span><span class="pun">[</span><span class="str">'utf'</span><span class="pun">],</span><span class="pln"> $str</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
   </span><span class="kwd">else</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
      </span><span class="kwd">return</span><span class="pln"> $str</span><span class="pun">;</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">?></span></code>

Функция utf8_convert() принимает 2 параметра: $str – наша строка

которую нужно перекодировать и $type – в какую кодировку нужно

кодировать (“w” – из utf в win, “u” – из win в utf). Как это применить

к нашим 3-м способам парсинга RSS думаю разберетесь, если хоть немного

знаете PHP.

источник

twitter.com facebook.com vkontakte.ru odnoklassniki.ru mail.ru ya.ru rutvit.ru myspace.com technorati.com digg.com friendfeed.com pikabu.ru blogger.com liveinternet.ru livejournal.ru memori.ru google.com bobrdobr.ru mister-wong.ru yahoo.com yandex.ru del.icio.us

Оставьте комментарий!

grin LOL cheese smile wink smirk rolleyes confused surprised big surprise tongue laugh tongue rolleye tongue wink raspberry blank stare long face ohh grrr gulp oh oh downer red face sick shut eye hmmm mad angry zipper kiss shock cool smile cool smirk cool grin cool hmm cool mad cool cheese vampire snake excaim question

Используйте нормальные имена. Ваш комментарий будет опубликован после проверки.

(войти без комментирования)

Имя и сайт используются только при регистрации

Если указать email (зарегистрироваться), то будет уведомление о новых комментариях.

Выберите человечка с поднятой рукой!