| Новости | 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[]