Новости | FAQ | Авторы | Документация | В действии | Библиотека |
Инструменты | Полезные ссылки | Хостинги | Скачать | Примеры | Форум |
Эдуард Габдуллин 05.05.2006 15:31
Полсле трех дней ожесточенных боев получилось следующее. За основу взят класс rss.p - автор Sanja v.2:############################## # В этот класс вынесен весь код, который # отвечает за чтение RSS потоков с других сайтов. @CLASS rss ############################## # Получение списка RSS ньюсфидов, которые не обновлялись больше часов, чем # указано в столбце min_refresh_period и их обновление @update_list[][limit;rss_feeds] ^if(def $form:limit){ $limit[$form:limit] $limit(^limit.int(15)) }{$limit(15)} $rss_feeds[ ^MAIN:pSQL.table{ SELECT uri, hours_to_keep FROM rss_list WHERE is_enabled="yes" AND last_update < ^date_sub_hour[;min_refresh_period] ORDER BY last_update }[$.limit($limit)] ] ^if(def $rss_feeds){ ^rss_feeds.menu{ ^update_feed[$rss_feeds.uri] ^MAIN:pSQL.void{ DELETE FROM rss_items WHERE pubdate < ^date_sub_hour[;$rss_feeds.hours_to_keep] AND feed_id = "$rss_feeds.uri" } } } ############################## # Повторное чтение RSS потока, разбор и запись в базу обновлений: @update_feed[feeduri][rss;cleanup;replacements;rss_text;xml;items;updatedcnt;counts;rss_version;date;title;link;description] # пытаемся загрузить RSS файл с помощью ^file::load # При этом может произойти целая туча неприятностей - другой сервер может не отвечать, # файл окажется испорчен или удалён - на этот случай мы пользуемся оператором ^try ^try{ $rss[^file::load[text;^untaint{$feeduri}; $.timeout(5) $.any-status(1) $.headers[ $.User-Agent[RSS aggregator from HimOil.ru] ] ]] # Поскольку парсер неспособен считать XML-элементы наподобие <item rdf:about="http:// # выскребаем их из документа: $replacements[^table::create{from to encoding="UTF-8" encoding="windows-1251" encoding="utf-8" encoding="windows-1251" encoding='utf-8' encoding='windows-1251' encoding="iso-8859-1" encoding="windows-1251" encoding='iso-8859-1' encoding='windows-1251' rdf: rdf_ &mdash^; - &hellip^; ...  ^; "^; " " " " " ©^; (c) «^; " »^; " &trade^; <sup>(TM)</sup> </rdf:RDF> </rss> xmlns= xmln_dis= xmlns: xmln_dis_ <rdf:li <rdf_li <rdf:Seq <rdf_Seq </rdf:Seq </rdf_Seq rdf:resource= rdf_resource= <admin:generatorAgent <admin_generatorAgent <rdf:RDF <rss version="2.0" dc:subject> subject> dc:creator> creator> dc:publisher> publisher> syn:updateFrequency> syn_updateFrequency> syn:updatePeriod> syn_updatePeriod> syn:updateBase> syn_updateBase> sy:updateFrequency> sy_updateFrequency> sy:updatePeriod> sy_updatePeriod> sy:updateBase> sy_updateBase> dc:language> language> dc:rights> rights> dcterms:isReferencedBy dcterms_isReferencedBy admin:errorReportsTo admin_errorReportsTo <content:encoded> <description> </content:encoded> </description> trackback:ping trackback_ping trackback:about trackback_about dc:date> pubDate>}] $rss_text[^untaint{$rss.text}] # Дочищаем текст: $rss_text[^rss_text.replace[$replacements]] # Это - на случай особо извращённых интерпретаций RSS (с <rdf:Seq>): ^if(^rss_text.match[rdf_Seq][]){ $replacements[^table::create{from to </channel>^taint[^#0A]<items>^taint[^#0A]</items>^taint[^#0A]</rss> </channel></rss>}] $rss_text[^rss_text.replace[$replacements]] } # Проверяем канал (RCCnews.ru) и испраляем кое-что ^if(^rss_text.match[RCCNews.ru][]){ $replacements[^table::create{from to </channel>^taint[^#0A]<image> <image> </items>^taint[^#0A]</rss> </channel></rss>}] $rss_text[^rss_text.replace[$replacements]] } $xml[^xdoc::create{$rss_text}] # Избавляемся от корневого тега RDF $items[^xml.select[/rss/channel/item]] $updatedcnt(0) ^if(def $items){ # Создаем табличку замен для каналов, которые любят ненужное форматирование $cleanup[^table::create{from to <img src="http://top.list.ru/counter?js=na^;id=427384^;t=57" border="0" height="1" width="1" alt="Рейтинг@Mail.ru"> <span style='font-family^: Tahoma, Verdana^;font-weight^: bold^;font-size^: 18px^;color^: #666666^;'></a> <span style='font-family^: Tahoma, Verdana^;font-weight^: bold^;font-size^: 18px^;color^: #666666^;'> <span style='font-family^: Tahoma^;font-size^: 11px^;color^: #666666^;text-decoration^: none^;'><br> <span style='font-family^: Tahoma^;font-size^: 11px^;color^: #666666^;text-decoration^: none^;'> </span> <br>^taint[^#0A]<br> <br /> ^taint[^#0A]<br> </p> <p> </p> <br> <br /> <br /><br /> <br />}] # Нам нужно узнать версию RSS-потока, который мы получили. # Тонкость в том, что у RSS 2.0 есть тэг PubDate, а у RSS 0.91 нету. # Поэтому для RSS 2 мы пользуемся тем, что есть, а для старых версий RSS # пользуемся политикой "дата, когда выкачали = дата создания" $rss_version[^xml.selectString[string(rss/@version)]] ^for[i](1;$items){ ^if($rss_version eq "2.0"){ $date{^xml.selectString[string(/rss/channel/item[position() = $i]/pubDate)]} ^if(def $date){ $date[^dtf:from822[$date]] }{ $date[^date::now[]] } }{ # Если мы имеем дело с RSS старой версии, берём текущую дату: $date[^date::now[]] } $title{^xml.selectString[string(/rss/channel/item[position() = $i]/title)]} $title[^title.replace[$cleanup]] $link{^xml.selectString[string(/rss/channel/item[position() = $i]/link)]} $description{^xml.selectString[string(/rss/channel/item[position() = $i]/description)]} $description[^description.replace[$cleanup]] # Проверка для канала Mabico.ru (эти идиоты шлют кучу пробелов переносов и точку) ^if(^description.length[] <= 14){ $description[$title] } $counts[^MAIN:pSQL.table{SELECT COUNT(*) AS cnt FROM rss_items WHERE link = "$link"}] ^if(^counts.cnt.int(1) == 0){ ^MAIN:pSQL.void{INSERT INTO rss_items (feed_id, title, link, description, pubdate) VALUES ('$feeduri', '$title', '$link', '$description', '^dtf:format[%Y-%m-%d %H:%i:%S;$date]') } ^updatedcnt.inc[] } } # Обновляем запись об этом RSS-фиде в базе: ^if($updatedcnt >= 0){^MAIN:pSQL.void{UPDATE rss_list SET last_update = ^MAIN:pSQL.now[] WHERE uri = "$feeduri"}} } }{ $exception.handled(1) } ############################## # Вывод кешированных RSS-элементов из базы @display[][rss_items] $rss_items[ ^MAIN:pSQL.table{ SELECT title, link, description, pubdate, rss_list.uri, rss_list.name, rss_list.allow_untaint FROM rss_items ^MAIN:pSQL.left_join[from;rss_list;rss_items.feed_id=rss_list.uri] ORDER BY pubdate DESC }[$.limit(20) $.offset(^if(def $form:skip){$form:skip}{0})] ] ^if(def $rss_items){ ^rss_items.menu{ <p> <b>^dtf:format[%d.%m.%Y %H:%i;$rss_items.pubdate] ^if(def $rss_items.title){ <a href="$rss_items.link">^untaint{$rss_items.title}</a> }{ Без заголовка }</b> <br /> ^if($rss_items.allow_untaint eq "yes"){ $desc[^untaint[as-is]{$rss_items.description}] }{ $desc[^untaint[html]{$rss_items.description}] } ^if(def $desc){ ^if(^desc.length[] >= 255){ $desc[^desc.left(255)…^; <a href="$rss_items.link">далее…^;</a>] } $desc }{ <i>Эта запись - без текста</i> } <br /> <span class="textSmall" style="font-style:italic"> ^if(def $rss_items.uri){ <a href="$rss_items.uri">$rss_items.name</a> }{ $rss_items.name } </span> </p> } }структура таблиц здесь:
############################################################ @date_sub_hour[sDate;iHour] $result[DATE_SUB(^if(def $sDate){$sDate}{NOW()},INTERVAL $iHour HOUR)] #end @date_sub_hour[]