RSS 1.0 w rękach maniaka

Fakt należący do tych, które dla jednych są banalnie oczywiste, a dla innych mogą być zaskoczeniem: pomimo identycznie brzmiącego akronimu różne wersje RSS to zupełnie inne formaty. Przeznaczenie wszystkich jest w zasadzie takie samo, jednak wbrew pozorom nie są to kolejne wersje tej samej specyfikacji, lecz kompletnie inne rozwiązania. RSS 0.9 (Rich Site Summary), RSS 2.0 (Really Simple Syndication) oraz format Atom to różne zastosowania języka XML specjalnie wymyślone dla celów umożliwienia syndykacji newsów, nagłówków, wiadomości itp. Natomiast RSS 1.0 (RDF Site Summary) to zastosowanie modelu danych RDF do opisu kanału informacyjnego — jedno z nieograniczonej ilości możliwych zastosowań RDF-a.

Ten drobny fakt, zapewne jest zupełnie nieistotny z punktu widzenia programów agregujących kanały RSS. Jednak dla zastosowań Sieci Semantycznej może mieć ogromne znaczenie. Dzięki temu łatwiej spojrzeć na RSS 1.0 nie tylko jak na kanał syndykacji, ale generalnie jak na jakieś dane w dogodnym formacie.

więcej niż plik XML

RSS 1.0 najczęściej jest przedstawiany w postaci pliku XML i programy odczytujące kanały RSS pewnie nie strawią żadnego innego formatu. Faktycznie jednak jest to tylko serializacja RDF-a do formatu RDF/XML i nic nie stoi na przeszkodzie, aby ten sam graf przedstawić w dowolny inny sposób, np. w N3 lub Turtle. Przykładowo zawartość kanału RSS z tego bloga w najbardziej zwartym zapisie N3 wyglądałaby jakoś tak:

@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rss: <http://purl.org/rss/1.0/> .
@prefix cc: <http://web.resource.org/cc/> .
@prefix dc: <http://purl.org/dc/elements/1.1/> .

<http://mimas.ceti.pl/tarpit/rss/simple.rdf> a rss:channel ;
dc:creator "MiMaS" ;
dc:language "pl" ;
rss:description "o inżynierii oprogramowania" ;
rss:image <http://mimas.ceti.pl/tarpit/img/ttp_rss_logo.png> ;
rss:items [ a rdf:Seq ;
rdf:_1 <http://mimas.ceti.pl/tarpit/archiwum/bilingual_blog> ;
rdf:_2 <http://mimas.ceti.pl/tarpit/archiwum/laczenie_grafow_rdf> ] ;
rss:link "http://mimas.ceti.pl/tarpit/" ;
rss:title "TheTarPit : smoliste grzęzawisko" ;
cc:license <http://creativecommons.org/licenses/by-nc-sa/2.5/> .

<http://mimas.ceti.pl/tarpit/archiwum/bilingual_blog> a rss:item ;
dc:creator "MiMaS" ;
dc:date "2006-01-04" ;
dc:subject "blog" ;
rss:description "In one of recent comments ..." ;
rss:link "http://mimas.ceti.pl/tarpit/archiwum/bilingual_blog" ;
rss:title "[en] Bilingual blog" .

<http://mimas.ceti.pl/tarpit/archiwum/laczenie_grafow_rdf> a rss:item ;
dc:creator "MiMaS" ;
dc:date "2006-01-02" ;
dc:subject "narzędzia", "semantic web", "technologie i rozwiązania" ;
rss:description "Skoro RDF umożliwia zapisywanie wszelkich danych ..." ;
rss:link "http://mimas.ceti.pl/tarpit/archiwum/laczenie_grafow_rdf" ;
rss:title "Łączenie grafów RDF w praktyce" .

<http://mimas.ceti.pl/tarpit/img/ttp_rss_logo.png> a rss:image;
rss:link "http://mimas.ceti.pl/tarpit/" ;
rss:title "TheTarPit : smoliste grzęzawisko" ;
rss:url "http://mimas.ceti.pl/tarpit/img/ttp_rss_logo.png" .

<http://creativecommons.org/licenses/by-nc-sa/2.5/> a cc:License ;
cc:permits cc:DerivativeWorks, cc:Distribution, cc:Reproduction ;
cc:prohibits cc:CommercialUse ;
cc:requires cc:Attribution, cc:Notice, cc:ShareAlike .

więcej niż kanał RSS

Skoro z RSS 1.0 można zrobić wszystko to, co z dowolnym innym grafem RDF, to pojawia się naturalny(?) odruch przeszukiwanie np. za pomocą SPARQL. Takie przeszukiwanie wcale nie musi być łatwiejsze niż użycie dowolnego mechanizmu przetwarzania XML-a i pewnie nie ma wiele sensu w przypadku pojedynczego kanału RSS. Jednak sytuacja zmienia się drastycznie jeśli dane z RSS, połączymy z czymś innym w większy i ciekawszy (a może tylko dziwniejszy?) model.

Na przykład — mam pod ręką wspomniany wyżej kanał RSS 1.0 z tego bloga, kanał RSS 1.0 z moich zakładek w del.icio.us i tradycyjnie już plik FOAF. Połączenie tego w jeden model wymaga znajomości kilku faktów, stwierdzających co (i czy w ogóle cokolwiek) mają te dane ze sobą wspólnego.

Na pierwszy rzut oka wydawać by się mogło, że połączenie między kanałem RSS bloga z profilem FOAF autora już w tych danych istnieje — poprzez adres bloga. Niestety drobny problem polega na tym, że w kanale RSS adres bloga jest wskazany jako Literal, a w profilu FOAF jako URI Reference. Oczywiście mógłbym zmodyfikować dane podając w dowolnym z tych plików drugą reprezentacje adresu, ale nie będę naginał faktów tylko po to, aby uzyskać ładny przykład ;-) Zamiast tego można użyć reguły N3, która przy użyciu cwm automagicznie wstawi wyrażenie foaf:made łączące osobę z kanałem RSS:

@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix rss: <http://purl.org/rss/1.0/> .
@prefix log: <http://www.w3.org/2000/10/swap/log#>.

# jesli osoba ma foaf:weblog,
# ktorego URI jest takie jak rss:link kanalu,
# to ta osoba foaf:made ten kanal

{ ?person a foaf:Person .
?channel a rss:channel .
?person foaf:weblog ?blog .
?blog log:uri ?bloguri .
?channel rss:link ?bloguri }
=> { ?person foaf:made ?channel } .

Powyższa regułą jest uniwersalna i pasuje do każdego profilu FOAF i każdego kanału RSS 1.0. Niestety nie udało mi się stworzyć podobnej dla połączenia z kanałem RSS z del.icio.us, dlatego informację o tym, że kolekcja na del.icio.us również „została zrobiona” przeze mnie, trzeba dopisać jawnie. Można to zrobić dodając kolejne wyrażenie z foaf:made ręcznie do pliku z profilem FOAF, albo w dodatkowej prostej regule, albo w dodatkowym pliku z patchem w notacji N3:

@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix delta: <http://www.w3.org/2004/delta#> .

# temu, kto ma foaf:homepage http://mimas.ceti.pl
# dodajemy jeszcze zapis, ze on foaf:made http://del.icio.us/mimas

{ ?m foaf:homepage <http://mimas.ceti.pl> }
delta:insertion { ?m foaf:made <http://del.icio.us/mimas> } .

W efekcie łączymy o dwa grafy więcej (jeden z patchem i jeden z regułami N3) niż mamy źródeł danych, ale wynika to tylko z tego, że nie przewidziałem takiego przykładu wcześniej i nie dodałem tych 2 linijek w profilu FOAF ;-) Teraz wystarczy tylko wydać polecenie (jedna linia):

cwm --rdf ~/public_html/pub/*.rdf
http://mimas.ceti.pl/tarpit/rss/simple.rdf
http://del.icio.us/rss/mimas
--patch=patch.n3 --think=rules.n3 > polaczone.rdf

i w pliku wynikowym mamy pośród mnóstwa danych również dwa brakujące wyrażenia foaf:made.

więcej niż potrzeba ;-)

Powstały model można przeszukiwać na najróżniejsze mniej lub bardziej irracjonalne sposoby — np. załóżmy, że z jakiegoś dziwnego powodu interesują mnie ostatnie pozycje (gdziekolwiek, na blogu lub w del.icio.us) na temat Sieci Semantycznej zrobione przez kogoś, ktoś hoduje karmi koty.[1] Zapytanie SPARQL na modelu RDF zawierający sklejone powyżej dane mogłoby wyglądać tak:

PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX pet: <http://purl.org/stuff/pets/>
PREFIX rss: <http://purl.org/rss/1.0/>
PREFIX dc: <http://purl.org/dc/elements/1.1/>

SELECT DISTINCT ?name ?title ?date ?link
WHERE {
?p a foaf:Person ;
foaf:name ?name ;
pet:hasPet ?cat ;
foaf:made ?channel .
?cat a pet:Pet ;
pet:hasProfile [ foaf:primaryTopic [ pet:species pet:Cat ] ] .
?channel a rss:channel ;
rss:items [ ?item [
a rss:item ;
rss:title ?title ;
dc:date ?date ;
rss:link ?link ;
dc:subject ?subj ] ] .
FILTER ( regex(?subj, "sem(antic )?web") ) .
} ORDER BY DESC(?date)

Trochę bardziej po polsku: pokaż nazwę, tytuł, datę i link pasujące do takiego szablonu: osoba, która się jakoś nazywa, ma jakiegoś zwierzaka i zrobiła jakiś kanał, przy czym ten zwierzak ma profil, którego głównym tematem jest coś o gatunku „kot”, natomiast wspomniany kanał to RSS z pozycjami zwierającymi coś, co ma nadany tytuł, datę, link oraz jakiś temat, przy czym uwzględniaj tylko takie pozycje, których temat to „semantic web” lub „semweb”, a na koniec posortuj to malejąco wg daty.

więcej możliwości

Pomijając dywagacje i spory o to, czy poszukiwanie takich informacji w ogóle do czegoś służy, zapytam inaczej — jak w porównywalnie prosty sposób uzyskasz taki wynik dysponując danymi źródłowymi w formacie innym niż RDF?

Oczywiście zaraz się znajdą młodzieńcy gotowi w dowolnym momencie wykazać, że każdy format można przerobić na każdy inny (zwłaszcza XML, np. via XSLT). Ale rzecz nie w tym, aby się dogrzebywać do ukrytych gdzieś zasobów, tylko żeby umożliwić łatwą (może nawet automatyczną(!)) agregację i współpracę z innymi zbiorami danych pochodzącymi z dowolnych źródeł... Dlatego pozwolę sobie wygłosić apel — jeżeli tylko masz taką możliwość udostępniaj swój kanał RSS w formacie RDF Site Summary — to nie boli, za to może niektórych uszczęśliwić... ;-)

[1] Wiem, że z tymi kotami w każdym możliwym przykładzie to ja już przesadzam ponad wszelką cierpliwość. Ale wbrew pozorom istnieją w gronie entuzjastów SW ludzie bardziej opętani — np. Danny Ayers hoduje między innymi kotkę o imieniu ... Sparql. ;-)

Komentarze

#1 | 2006.01.09 10:33 | gshegosh

Trochę mnie zastanawia to, że z jednej strony wnioskowanie jest automatyczne, grafy się łączą, itp. i można z tego zbioru informacji wyciągnąć jakąś wiedzę.
Tylko jak do tego "automagizmu" ma się to, że jeśli czegoś tam nie przewidziałeś w swoim FOAF, to trzeba to do niego dodać?
Jeśli zapuszczę jakiegoś agenta, który będzie miał coś tam dla mnie w sieci odnaleźć, nie będzie on przecież na tyle inteligentny, by coś w Twoim FOAF dodać, ani nawet na tyle by Cię o to poprosić ;)

#2 | 2006.01.09 10:45 | MiMaS

Można wyciągnąć tylko tą wiedzę, która tam jest. Jeśli jej nie ma to żaden agent sobie nie poradzi. Na przykład nigdzie nie jest powiedziane, że kanał RSS pod adresem http://del.icio.us/rss/mimas ma cokolwiek wspólnego z RSS-em pod adresem http://mimas.ceti.pl/tarpit/rss/simple.rdf. My wiemy (a przynajmniej zakładamy), że cechą wspólną tych kanałów jest osoba autora (że niby ja) ale to nigdzie nie jest powiedziane w tych danych. Ani w jednym ani w drugim RSS-ie. Skąd zatem ma to wiedzieć agent, choćby i najsprytniejszy?? Przecież nie każemy mu zgadywać na podstawie wspólnych 5 literek w adresach RSS-ów, prawda?

Spójrz na to inaczej — i tak jest dobrze, że istnieje możliwość połączenia tych kanałów RSS, np. wskazując (nawet w zupełnie innym miejscu jak np. plik FOAF), że autorem obu jest ta sama osoba. To i tak znacznie więcej niż mógłbyś uzyskać z danych publikowanych w jakiś inny sposób. ;-)

 

Uwaga: Ze względu na bardzo intensywną działalność spambotów komentowanie zostało wyłączone po 60 dniach od opublikowania wpisu. Jeżeli faktycznie chcesz jeszcze skomentować skorzystaj ze strony kontaktowej.