PHP парсване на XML новини за твоя сайт

Ще ти покажа малко PHP код, с който много лесно можеш да извлечеш новини от някой сайт за новини, който има RSS хранилка (RSS feed). Много хора дори не предполагат, колко елементарно се прави това. Дори да имаш само бегли познания за PHP, можеш просто да копираш този код (даден с тъмнозелено долу) в някой от php файловете на твоя сайт (например index.php) и той ще покаже новини от друг сайт в твоя сайт. Изискването е новините да са в RSS 2.0 формат.

В този пример новините представляват статии от statii.net. Още като влезеш в началната страница на сайта вдясно виждаш малки оранжеви иконки и връзката "всички статии". Това е RSS хранилка, която захранва с най-новите статии от сайта. Под всички се разбира последните 10 статии, като най-новите са най-отгоре. Това ограничение може да е различно и се задава от собственика на сайта, който осигурява RSS. Ако застанеш с мишката над линка ще видиш в статус бара на браузъра адреса http://statii.net/feed. Ако посетиш тази връзка ще видиш последните статии, като кода на страницата, която гледаш е в XML формат. Ако браузъра е нов той сам ще форматира съдържанието и ще го покаже удобно за четене, но ако погледнеш кода на страницата ще видиш XML. Кода на страницата с Internet Explorer се вижда с натискане на десен бутон на мишката в страницата и после от падащото меню се избира View Source, при Firefox опцията е View Page Source. В този пример XML-а ще изглежда така:


<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
    xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:atom="http://www.w3.org/2005/Atom"
    xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
    xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
    >

<channel>
    <title>Директория за статии</title>
    <atom:link href="http://statii.net/feed/" rel="self" type="application/rss+xml" />
    <link>http://statii.net</link>
    <description>Напиши нова статия. Вземи статии за твоя сайт.</description>
    <lastBuildDate>Sat, 08 Aug 2009 09:00:05 +0000</lastBuildDate>

    <generator>http://wordpress.org/?v=2.8</generator>
    <language>en</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
    <item>
      <title>Градинска ножица Ciso на Bosch</title>

      <link>http://statii.net/2009/%d0%b3%d1%80%d0%b0%d0%b4%d0%b8%d0%bd%d1%81%d0%ba%d0%b0
-%d0%bd%d0%be%d0%b6%d0%b8%d1%86%d0%b0-ciso-%d0%bd%d0%b0-bosch/</link>
      <comments>http://statii.net/2009/%d0%b3%d1%80%d0%b0%d0%b4%d0%b8%d0%bd%d1%81%d0%ba
%d0%b0-%d0%bd%d0%be%d0%b6%d0%b8%d1%86%d0%b0-ciso-%d0%bd%d0%b0-bosch/#comments</comments>
      <pubDate>Sat, 08 Aug 2009 08:59:49 +0000</pubDate>
      <dc:creator>toto</dc:creator>
      <category><![CDATA[Градинарство]]></category>
      <category><![CDATA[Bosch]]></category>
      <category><![CDATA[бамбук]]></category>

      <category><![CDATA[градина]]></category>
      <category><![CDATA[ножица]]></category>
      <category><![CDATA[Цветя]]></category>

      <guid isPermaLink="false">http://statii.net/?p=326</guid>
      <description><![CDATA[Първата в света акумулаторна градинска ножица с вграден
литиево-йонен акумулатор.
Хубавата градина изисква много грижи. Подрязването на клони, които следва да се почистят с
градинска ножица е уморително, а понякога може да предизвика и болки в ставите и мускулите на
ръката. Тези проблеми се разрешават с помощта на Ciso &#8211; първата в света акумулаторна
градинска ножица [...]]]></description>
      <wfw:commentRss>http://statii.net/2009/%d0%b3%d1%80%d0%b0%d0%b4%d0%b8%d0%bd%d1%81
%d0%ba%d0%b0-%d0%bd%d0%be%d0%b6%d0%b8%d1%86%d0%b0-ciso-%d0%bd%d0%b0-bosch/feed/</wfw:commentRss>
      <slash:comments>0</slash:comments>

</item>

... още елементи item ...

    </channel>
</rss>

От реда rss version="2.0" се вижда, че този XML е във формат RSS версия 2.0.

PHP код за извличане и на RSS новини


<?php

        # ganbox.com: парсва RSS новини в масив arrFeeds
       $url='http://statii.net/feed/'; # адрес на RSS хранилката
       $doc = new DOMDocument();
    $doc->load($url);
    $arrFeeds = array();
    foreach ($doc->getElementsByTagName('item') as $node) {
        $itemRSS = array (
            'title'=>$node->getElementsByTagName('title')->item(0)->nodeValue,
            'desc' =>$node->getElementsByTagName('description')->item(0)->nodeValue,
            'link' =>$node->getElementsByTagName('link')->item(0)->nodeValue,
            'date' =>$node->getElementsByTagName('pubDate')->item(0)->nodeValue,
            );
        array_push($arrFeeds, $itemRSS);
    }

        # ganbox.com: отпечатване на feedLimit на брой новини от масива arrFeeds
       $feedLimit=0; # ако feedLimit=0 се показват всичките
       $feedCount=0;
        foreach($arrFeeds as $oneItem){
            # ако твоя сайт има кодиране cp1251, тогава махни коментара # на следващия ред
           # foreach($oneItem as $key=>$value){$oneItem[$key]=iconv('utf-8','cp1251',$value);}
           $feedCount++;
            print '<div class="feedItem"><h3 class="feedTitle"><a href="'.$oneItem['link'].'"
                class="feedLink">'.$oneItem['title'].'</a></h3>';
            print '<p class="feedDesc">'.$oneItem['desc'].'</p>';
            print '</div>';
            if($feedLimit>0 && $feedCount>=$feedLimit) break;
        }
?>

Това е всичко. Сложил съм класовете feedItem, feedTitle, feedLink и feedDesc за по-лесно управление на изгледа от CSS файл. Ако искаш сложи всичко в един div контейнер.

Масива arrFeeds съдържа и поле date, в което е датата на публикуване. Ако искаш може да показваш и нея с още един ред: print '<p class="feedDate">'.$oneItem['desc'].'</p>';  поставен след реда съдържащ feedDesc.

Важно е да се отбележи, че използвания метод зарежда всички новини в паметта на сървъра, където е твоя сайт. Ако новините са много или текста им е прекалено дълъг това ще доведе до счупване на страницата на твоя сайт или в най-добрия случай на забавяне на зареждането. Трябва да се увериш, че хранилката, която ползваш показва само част от текста, както е в statii.net или показва само най-новите X на брой новини. Друг вариант е да се абонираш само за тема, която те интересува. Продължавай да четеш 🙂

Избор на категория със статии

Ако не искаш да показваш всички статии, а само статии от определена категория първо влез в категорията. Например в  "Практически съвети"  тогава отдясно се показва трета връзка "тази категория" и може да видиш, че линка има адрес http://statii.net/tema/дом-и-семейство/практически-съвети/feed/  Сложи този адрес в променливата $url в началото на кода и ще се извличат само статии от тази категория. Нещо повече - може да извличаш само статии, които съдържат определена дума например seo. За да направиш това първо извърши търсене в сайта statii.net от търсачката най-горе по думата seo. Тогава третата връзка в дясно се променя на "това търсене" с адрес на линка http://statii.net/search/seo/feed/ сложи този адрес в променливата $url и ще получаваш само статии съдържащи думата SEO.

Ползите за твоя сайт

Получаваш автоматично и безплатно ново съдържание и посетителите на твоя сайт, започват да го посещават по-често. Търсачките забелязват, че твоя сайт е динамичен и го оценяват по-високо. Внимание! Задължително оставяй реална връзка към източника на новината (така както е в примера), защото със сигурност новината вече е индексирана от търсачките и ако няма връзка това ще се отчете като кражба на съдържание и сайта ти ще започне да се класира по-лошо.

Трябва да внимаваш съдържанието с новини което включваш на всяка страница да не бъде прекалено много. То трябва да бъде не повече от 20% от общото съдържание на страницата. В противен случай ще получиш негативен SEO ефект, защото чуждото съдържание ще размие тематиката на твоя сайт. Затова в горния пример може да ползваш feedLimit=3 в страниците с по-малко текст.

Този PHP код е тестван и все пак ако има проблем пиши коментари по статията.

Прочетена:18489
1 - лоша2 - слаба3 - средна4 - добра5 - отлична (1 гласа, оценка: 5,00 от 5. Моля изберете оценка!)
Loading...
Георги Стефанов
Магистър по информатика, който се занимава с компютри от 1988 г., професионално с програмиране от 1998 г., а с уеб технологии от 2002 г. Има богат опит при оптимизиране на бизнес сайтове. Повече от 15 години развива успешно свои уеб проекти и работи с български и международни компании за постоянно подобряване на техните сайтове и увеличаване на онлайн продажбите. 

30 comments on “PHP парсване на XML новини за твоя сайт”

  1. мерси за урока. имам един въпрос - знаеш ли други сайтове с български новини, от които може да се дърпа безплатно?

  2. Има доста сайтове с RSS новини ето един dnes.bg/rss_info.php

  3. GAN много хубав урок но при мен на сайта излиза маймунски знаци, защото кодировката мие 1252 а там е utf-8 как да я оправя?

  4. След реда: foreach($arrFeeds as $oneItem){
    Добави кода:
    foreach($oneItem as $key=>$value){ $oneItem[$key]=iconv('utf-8','cp1252',$value); }

  5. Gan Браво стана чак сега погледнах как си го направил мерси
    Черпихте една голяма виртуална бира така трябва да прави всеки това е труд все пак 🙂

  6. Gan а можели да се направи с картинките да показва ...има и такива емисии. Аз пробвах да сложа още един ред 'image' =>$node->getElementsByTagName('pubDate')->item(0)->nodeValue, Но грешка ми дава.

  7. Това pubDate е датата на публикуване на статията. Картинките обикновено са в текста description и се подават като HTML от RSS в такъв случай не трябва да променяш нищо. Дай връзка към страницата в която се опитваш да покажеш RSS.

  8. Здрасти. 🙂 Ами ако искаш да извлечеш картинката от enclosure таг? Някои знае ли как става това, търсих из нета но не мога да намеря. Благодаря предварително.

  9. Прави се лесно, защото enclosure тага съдържа само пътя до мултимедиен файл, а не самия файл. Дай връзка към RSS който съдържа enclosure и може да напиша пример.

  10. Ок ако ми напишеш сте сам ти много благодарен дакажем с news.ibox. bg/rss_1 . Може и само реда на пхп да напищеш. Мерси.

  11. За парсване на enclosure таг, след реда:
    date' =>$node->getElementsByTagName('pubDate')->item(0)->nodeValue,
    Добави реда:
    'enclosure' => $node->getElementsByTagName('enclosure')->item(0)->getAttribute('url'),
    Така в масива $itemRSS ще имаш и пътя до мултимедийния файл.

    Адаш имаш да черпиш 😉

  12. ok А за да я прнтне какво да напиша? Така не я показва не знам защо. Сигурно трябва да се напише нещо и в foreach($arrFeeds as $oneItem){

  13. Е разбира се, че ще трябва да го изведеш от масива. Реда:
    print '<p class="feedDesc">'.$oneItem['desc'].'</p>';
    трябва да стане нещо като:
    print '<p class="feedDesc"><img src="'.$oneItem['enclosure'].'" align="left" />'.$oneItem['desc'].'</p>';

  14. Здр. Искам да те питам защо ми изкарва тази грешка на ред 65
    'enclosure' => $node->getElementsByTagName('enclosure')->item(0)->getAttribute('url'),
    като го махна всичко е ок но сложа ли го дава грешка. Това е за да изкарам и картинката от http://news.ibox.bg/rss_1

  15. Очевидно е. Някои от новините нямат enclosure елемент и заради тях гърми. Трябва леко да се промени кода. Там където пълниш масива $itemRSS става:
    'enclosure' => $node->getElementsByTagName('enclosure'),
    Там където показваш новините става:

    $articlesOutput .= '<p class="feedDesc">'.(is_object($oneItem['enclosure']->item(0)) ? '<img src="'.$oneItem['enclosure']->item(0)->getAttribute('url').'" width="50" alt="" />' : '').$oneItem['desc'].'</p>';
  16. Скрипта работи,но имам един проблем как да взема новини от сайт с енкодинг utf-8 и да ги сложа на сайта си скойто има енкодинг windows 1251

  17. Отговорът на твоя въпрос се намира в самия код. Прочети внимателно коментарите в кода.

  18. На мен ми дава грешка - Parse error: syntax error, unexpected T_OBJECT_OPERATOR, expecting ')' in /users/xteamonl/public_html/consultcommerce99/index2.php on line 79

    Възможно ли е да е от версията на PHP?

  19. Ако близо до ред 79 има: $doc = new DOMDocument();
    значи е заради версията. Този пример изисква PHP 5.

  20. Здр. чудесна статия, но бихте ли ми казали и как да огранича до напримерно 10, 20 знака да се показват от всяка новина?

  21. Използва се функция $text=mb_substr($text,0,20);

  22. Здравейте, и аз се опитва да съкратя текста, но как точно се поставя $text=mb_substr($text,0,20); пробвам но все не се получава

  23. От това "все не се получава" не е ясно какъв е проблема. Ако PHP дава грешка (или бяла страница) това означава, че на хостинга няма библиотеката mb_string. Ако функцията сработва, но не отрязва правилния брой символи може да пробвате с поставяне на четвърти параметър за енкодинга. Например $text=mb_substr($text,0,20,'UTF-8'); или $text=mb_substr($text,0,20,'cp1251'); в зависимост от това кой енкодинг ползвате.

  24. mb_string имам поддръжка, но на кой ред се слага? как би изглеждал нагледно кода? Благодаря (надявам се това да бъде полезно и за другите потребители)

  25. Ако трябва да съкратя заглавията до 20 символа, бих направил следното. В цикъла foreach, преди операторите print и след реда $feedCount++; ще поставя следния код:
    if(mb_strlen($oneItem['title'])>20){
    $oneItem['title']=mb_substr($oneItem['title'],0,20,'UTF-8').'...';
    }

  26. Имам един въпрос. Скрипта си бачка, но във feed-a имам една новина, към която няма текст, а само снимка, което ми разформатира текста. Възможно ли е да се направи ако $oneItem['desc'] е 0 да се слагат няколко тага?

  27. Защо не? Контролът е при вас. Можете в този случай да сложите всичко. Например

     
споделиха
linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram