3. 3
Abstract. Lucrarea de fata ˆsi propune s˘ ofere o vedere de ansam-
¸˘ ı¸ a
blu asupra unor domenii de interes precum RDF(Resource Description
Framework), RDFa, SPARQL. Va fi prezentat˘ ¸i libr˘ria SemWeb care
as a
ofer˘ un API pentru lucrul cu RDF din aplicatii .NET. Ca studiu de
a ¸
caz se ofer˘ o aplicatie intitulat˘ diSPARQL care alc˘tuie¸te cu ajutorul
a ¸ a a s
unui crawler o list˘ de puncte terminale SPARQL. Acestea vor putea fi
a
interogate pentru obtinerea unor informatii de interes, sau se va putea
¸ ¸
afla starea unui punct terminal (dac˘ poate r˘spunde cererilor de in-
a a
terogare).
1 Tehnologii - Scurt˘ prezentare
a
1.1 RDF ¸i RDFa
s
RDF reprezint˘ un cadru abstract de descriere a resurselor de interes ˆ even-
a ın
tualitatea interog˘rii ulterioare a informatiilor. Aceast˘ abordare a Web-ului
a ¸ a
semantic prive¸te informatiile existente ca o baz˘ de date. Informatiile stocate
s ¸ a ¸
RDF sunt specificate sub forma unor triple (Subiect, Predicat, Obiect). Subiectul
denot˘ resursa, Predicatul denot˘ o anumit˘ ˆ sire a Subiectului, ¸i define¸te
a a a ınsu¸ s s
relatia pe care o are Subiectului cu Obiectul. O colectie de triple poate fi privit˘
¸ ¸ a
ca fiind un graf orientat, ˆ care Subiectul si Obiectul sunt noduri, iar Predi-
ın
catul reprezint¸ muchia dintre cele dou˘ directionat˘ de la Subiect la Obiect.
a a ¸ a
Fiecare valoare din triplu are la baza un URI (Uniform Resource Identifier) care
identific˘ unic o resurs˘.
a a
RDFa reprezint˘ o recomandare W3C pentru adnotarea elementelor prezente
a
ˆ
ıntr-o pagin˘ web. Adnotarea se face prin ad˘garea de atribute (about, rel,
a a
href property, content, datatype, typeof ) elementelor XHTML existente. Ben-
eficiul adus de RDFa este faptul c˘ datele existente ˆ
a ıntr-o pagin˘ web vor putea
a
stoca metadate care pot fi ulterior descoperite de utilizatori. Cu ajutorul acestor
atribute se pot forma triple RDF care vor contine informatie reutilizabil˘.
¸ ¸ a
<div xmlns:dc="http://purl.org/dc/elements/1.1/"
about="http://students.info.uaic.ro/~elena.carjan/WADE/proiect.pdf">
<span property="dc:title">diSparql</span>
<span property="dc:creator">Alexandra Iacob</span>
<span property="dc:date">01-19-2011</span>
</div>
1.2 SPARQL
SPARQL reprezint˘ un limbaj de interogare asem˘n˘tor SQL-ul recomandat de
a a a
Consortiul W3 din 2008. O interogare SPARQL este compus˘ din variabile ce
a
sunt legate de o anumit˘ parte component˘ a unui triplu (sunt precedate de
a a
semnul ’ ?’), constrˆngeri (utilizarea cuvˆntului rezervat FILTER) ¸i alte reguli
a a s
de modelare. Un beneficiu al acestui limbaj de interogare ˆ reprezint˘ faptul c˘
ıl a a
utilizatorul va scrie o interogare neambigu˘.
a
4. 4
2 Biblioteca SemWeb
2.1 Generalit˘¸i[1]
at
SemWeb este o bibliotec˘ .NET care permite lucrul cu date stocate ˆ model
a ın
RDF. Ofer˘ mai multe clase de citire, scriere, manipulare ¸i interogare RDF. Nu
a s
ofer˘ suport pentru ontologii OWL.
a
Clasele cele mai importante ale bibliotecii se g˘sesc ˆ spatiul de nume
a ın ¸
SemWeb. Acestea sunt ˆ num˘r de 4 ¸i anume: Resource, Statement, State-
ın a s
mentSource, StatementSink.
Clasa Resource este abstract˘ ¸i ofer˘ suport pentru termenii triplelor RDF.
as a
Resource are dou˘ subclase Entity ¸i Literal. Subiectul ¸i Obiectul dintr-un triplu
a s s
RDF pot fi exprimati folosind clasa Entity. Nodurile blank pot fi utilizate cu
¸
ajutorul clasei BNode care este o subclas˘ a clasei Entity. Predicatul dintr-un
a
triplu RDF poate fi exprimat cu ajutorul clasei Literal.
Structura Statement reprezint˘ o propozitie RDF. Statement este de fapt o
a ¸
structur˘ si nu o clas˘ din motive de scalabilitate, o aplicatie lucrˆnd cu un num˘
a a ¸ a a
ridicat de triple. Acest struct este compus din urm˘toarele cˆmpuri Subject - de
a a
tipul Entity, Predicate de tipul Entity ¸i Object care poate fi Resource.
s
Cu alte cuvinte construirea unui triplu va arat˘ astfel:
a
new Statement(
new Entity("http://www.example.org/SemWeb"),
new Entity("http://www.example.org/hasName"),
new Literal("My Semantic Web library!") );
sau
new Statement(
new Entity("http://www.example.org/SemWeb"),
new Entity("http://www.example.org/relatedTo"),
new BNode() );
care folose¸te nodul vid.
s
Cˆnd se construie¸te un obiect de tipul Entity nu are loc nici o validare a
a s
URI-ului folosit ˆ constructor. Validarea trebuie f˘cut˘ de utilizator.
ın a a
Interfata StatementSource reprezint˘ o colectie de Statement. Este imple-
¸ a ¸
mentat˘ de clase precum RdfXmlReader ¸i N3Reader care folosesc anumite for-
a s
mate pentru a stoca informatiile. Metoda cea mai important˘ a acestei interfete
¸ a ¸
o reprezint˘ Select.
a
Interfata StatementSink este folosit˘ pentru procesarea unui set de State-
¸ a
ment. Este implementat˘ de clase precum RdfXmlWriter ¸i N3Writer. ˆ mo-
a s In
mentul implement˘rii acestei interfete trebuie suprascris˘ metoda Add, ˆ care
a ¸ a ın
utilizatorul poate opta s˘ retin˘ instantele de tip Statement ˆ
a ¸ a ¸ ıntr-un ArrayList
sau poate s˘ proceseze fiecare instant˘ ˆ parte la momentul ad˘g˘rii.
a ¸a ın a a
O alt˘ clas˘ important˘ a acestei biblioteci o reprezint˘ MemoryStore. La
a a a a
baz˘ poate fi privit ca fiind un ArrayList de instante Statement. Aceasta im-
a ¸
plementeaz˘ atˆt StatementSource cˆt ¸i StatementSink, ceea ce permite apelul
a a a s
5. 5
metodei Add, dar ¸i Select. Deoarece implementeaz˘ ¸i IEnumerable aceast˘ clas˘
s as a a
este folosit˘ pentru iteratie prin Statement-urile care ne intereseaz˘.
a ¸ a
MemoryStore ms = new MemoryStore();
datasource.Select(ms);
foreach (Statement stmt in ms)
Console.WriteLine(stmt);
2.2 Utilizare ˆ cadrul proiectului
ın
Biblioteca SemWeb ofer˘ suport pentru a interoga prin HTTP puncte terminale
a
SPARQL. Clasa utilizat˘ ˆ cadrul proiectului este SparqlHttpSource.
a ın
SparqlXmlQuerySink xml = new SparqlXmlQuerySink(Console.Out);
SparqlHttpSource source = new SparqlHttpSource("http://DBpedia.org/sparql");
source.RunSparqlQuery("SELECT * WHERE { ?s ?p ?w . }", Console.Out);
source.RunSparqlQuery("SELECT * WHERE { ?s ?p ?r . }", xml);
3 Aplicatia diSPARQL
¸
Cerintele de dezvoltare ale acestui proiect sunt urm˘toarele: S˘ se realizeze
¸ a a
un set de servicii Web care ofer posibilitatea descoperirii de puncte-terminale
SPARQL, eventual pe baza unui crawler. Datele descoperite vor putea fi in-
terogate via SPARQL, iar documentele HTML generate vor include constructii ¸
RDFa modelˆnd resursele de interes. De asemenea, se va implementa un serviciu
a
de pinging util pentru testarea faptului c˘ un punct terminal SPARQL mai este
a
operational. Se vor preveni posibilele atacuri ce pot surveni.
¸
Aplicatia a fost dezvoltat˘ folosind limbajul de programare C# ¸i s-a recurs
¸ a s
la servicii web ˆ ASP.NET. Implementarea ofer˘ 2 servicii web fiecare avˆnd
ın a a
mai multe metode de interes.
Serviciul de c˘tare are ca scop identificarea punctelor terminale SPARQL.
a
Acest lucru este realizat cu ajutorul unui crawler care va primi ca seed-uri link-
urile paginilor de c˘tare de la Bing ¸i Google. Apoi va retine toate elementele
a s ¸
de tip ¡a¿ mai exact atributul href din pagina respectiv˘. Lista obtinut˘ va
a ¸ a
deveni lista cu seed-uri pentru urm˘toarea parcurgere a algoritmului urm˘rindu-
a a
se s˘ se ating˘ adˆncimea dorit˘ ˆ momentul rul˘rii. Pentru fiecare pagina noua
a a a a ın a
descoperit˘ se va ˆ
a ıncerca s˘ se ruleze o interogare SPARQL (folosind biblioteca
a
SemWeb prezentat˘ anterior), cunoscˆndu-se astfel dac˘ pagina este un punct
a a a
terminal SPARQL sau nu.
Serviciul de interogare are ca scop verificarea st˘rii unui punct terminal
a
SPARQL, dar ¸i rul˘rea unei interog˘rii SPARQL pe un anumit punct terminal.
s a a
Aceste actiuni sunt ˆ
¸ ındeplinite tot folosindu-se biblioteca SemWeb.
3.1 Biblioteca Crawler
Totalitatea claselor care sunt necesare cre˘rii serviciilor web mentionate mai sus
a ¸
se afl˘ ˆ aceast˘ bibliotec˘. Biblioteca este ad˘gat˘ ca referint˘ local˘ ˆ cadrul
a ın a a a a ¸a a ın
proiectului aplicatiei Web care implementeaz˘ serviciile.
¸ a
6. 6
Csv Parser Aceast˘ clas˘ are ca functionalitate salvarea unei instante Hashtable
a a ¸ ¸
ˆ
ıntr-un fi¸ier format Comma Separated Values. Ofer˘ 2 proceduri: LoadFromFile
s a
respectiv SaveToFile.
Html Parser[2] Acest fi¸ier ofer˘ 2 clase: Html Tag ¸i Html Parser. Cea de-a
s a s
doua va fi folosit˘ pentru a parsa continutul unei pagini web. Html Tag reprezint˘
a ¸ a
un element HTML ¸i are ca membru un obiect de tipul Dictionary cu dou˘
s a
cˆmpuri de tip String - aici vor fi memorate toate atributele pe care le va g˘si
a a
parserul. Html Parser
Site Crawler Clasa Site Crawler are mai multe metode interesante pentru
aplicatia de fata.
¸ ¸
– String DownloadPage(String url) Este folosit˘ clasa WebRequest pentru
a
accesarea unei anumite pagini cu o anumit˘ adres˘. Fiecarei pagini i se va
a a
citi codul surs˘ acesta fiind returnat din metod˘.
a a
WebRequest wrGETURL;
wrGETURL = WebRequest.Create(url);
wrGETURL.Method = "GET";
WebResponse myResponse = wrGETURL.GetResponse();
StreamReader sr = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8);
string result = sr.ReadToEnd();
sr.Close();
myResponse.Close();
return result;
– Hashtable GetListOfLinks(String page) Avˆnd ca parametru de in-
a
trare ¸irul de caractere ce reprezint˘ ˆ
s a ıntrega pagin˘, aceast˘ metod˘ va folosi
a a a
metoda ParseTag din cadrul clasei Html Parser pentru a obtine o list˘ com-
¸ a
plet˘ a leg˘turilor existente. ˆ cadrul acestei metode este f˘cut˘ o optimizare
a a In a a
ˆ ceea ce prive¸te num˘rul de leg˘turi pe care le-am putea g˘si ˆ interiorul
ın s a a a ın
paginii. Sunt luate ˆ considerare doar leg˘turile a c˘ror element href ˆ
ın a a ıncepe
cu ¸irul de caractere http.
s
O alt˘ ˆ
a ımbun˘t˘¸ire adus˘ acestei metode este folosirea unei instante a clasei
a at a ¸
Hashtable. Paginile retinute vor fi unice. Dac˘ ˆ elementul HTML este oferit
¸ a ın
¸i atributul name atunci acesta va fi folosit drept cheie ˆ momentul ad˘ug˘rii
s ın a a
ˆ Hashtable, altfel folosindu-se tot elementul href.
ın
while (parse.ParseNext("a", out tag))
{
string href, name;
tag.Attributes.TryGetValue("href", out href);
tag.Attributes.TryGetValue("name", out name);
7. 7
if (href != null && href.StartsWith("http"))
{
if (name == null)
name = href;
try
{
res.Add(name, href);
}
catch (System.ArgumentException)
{
//Console.WriteLine("Item already added");
}
}
– bool IsEndpoint(String url) Metoda returneaz˘ valoarea true dac˘ la
a a
adres˘ oferit˘ ca parametru se g˘se¸te un punct terminal SPARQL. Este
a a a s
folosit˘ libr˘ria SemWeb[1]. Se va c˘uta s˘ se trateze cazurile de exceptie -
a a a a ¸
ˆ eventualitatea ˆ care adresa nu reprezint˘ un punct terminal valid atunci
ın ın a
se va arunca exceptia System.net.WebException.
¸
try{
SparqlHttpSource source = new SparqlHttpSource(url);
diSparqlResultSink sink = new diSparqlResultSink();
source.RunSparqlQuery("SELECT * WHERE { ?s ?p ?q. } LIMIT 1", sink);
result = sink.resultsCounter > 0;
}
catch (System.Net.WebException)
{}
return result;
ˆ aceast˘ secvent˘ de cod s-a folosit o clas˘ nou˘: diSparqlResultSink. Aceast˘
In a ¸a a a a
clas˘ a fost creat˘ pentru a oferi siguranta faptului c˘ interogarea s-a exe-
a a ¸ a
cutat ¸i a returnat cel putin un rezultat. Aceast˘ clas˘ implementeaz˘ clasa
s ¸ a a a
abstract˘ oferit˘ de SemWeb ¸i anume QueryResultSink, ¸i suprascrie metod˘
a a s s a
de Add care este apelat˘ de fiecare dat˘ cˆnd se obtine un nou triplu ˆ urma
a a a ¸ ın
interog˘rii unui punct terminal SPARQL. La fiecare apel al metodei se va
a
incrementa un contor, iar ˆ momentul finaliz˘rii executiei se va ¸ti num˘rul
ın a ¸ s a
final de ˆ ınregistr˘ri g˘site.
a a
public class diSparqlResultSink : QueryResultSink
{
public Int32 resultsCounter = 0;
public override bool Add(VariableBindings result)
{
foreach (Variable var in result.Variables)
{
if (var.LocalName != null && result[var] != null)
8. 8
{
resultsCounter++;
}
}
return true;
}
}
– void FindPoints(int depth) Metoda are la baza algoritmul de functionare¸
al unui crawler. Acesta prime¸te 2 pagini de start. ˆ urma pars˘rii paginilor
s In a
respective va obtine o nou˘ list˘ de leg˘turi. Paginile din aceast˘ list˘ vor
¸ a a a a a
fi trecute prin metoda IsEndpoint, dac˘ r˘spunsul este da, atunci aceast˘
a a a
pagin˘ va fi ad˘ugat˘ ˆ lista de puncte terminale SPARQL, altfel va fi
a a a ın
ad˘ugat˘ ˆ lista cu pagini de c˘utat mai departe. ˆ functie de adˆncimea
a a ın a In ¸ a
setat˘ algoritmul descris pentru un nivel va fi aplicat pentru celelalte nivele.
a
Num˘rul de pagini g˘site la nivelul al 3-lea a fost de 30000 de pagini, din
a a
care ˆ jur de 25 de puncte terminale SPARQL.
ın
Int32 currentDepth = 0;
Hashtable current = this._pages;
while (currentDepth < this._depth)
{
Console.WriteLine("Current depth: " + currentDepth);
currentDepth += 1;
Hashtable newList = new Hashtable();
foreach (DictionaryEntry page in current)
{
if (IsEndPoint(page.Value.ToString()) == false
{
Hashtable list = GetListOfLinks(page.Value.ToString());
Console.WriteLine("foreach page not endpoint: " + list.Count);
foreach (DictionaryEntry mem in list)
{
try
{
newList.Add(mem.Key, mem.Value);
}
catch (System.ArgumentException)
{
Console.WriteLine("Item already added");
}
}
}
else
{
try
{
9. 9
this._sparql.Add(page.Key, page.Value);
Console.WriteLine("Adding endpoint: " + page.Value);
}
catch (System.ArgumentException)
{
}
}
}
current.Clear();
Console.WriteLine(newList.Count)
foreach (DictionaryEntry val in newList)
{
current.Add(val.Key, val.Value);
}
Console.WriteLine(current.Count);
foreach (DictionaryEntry mem in newList)
{
try
{
this._pages.Add(mem.Key, mem.Value);
}
catch (System.ArgumentException)
{
//Console.WriteLine("Item already added");
}
}
newList.Clear();
Console.WriteLine();
}
– LoadFromCSV ¸i SaveToCSV Metodele vor fi folosite pentru p˘strarea
s a
punctele descoperite la un moment dat ˆ
ıntr-un fi¸ier ˆ format Comma Sep-
s ın
arated Values.
Interogate Clasa Interogate ofer˘ metoda cea mai important˘ a aplicatiei ¸i
a a ¸ s
anume aceea ˆ care se va rula o interogare la adresa indicat˘. Datele obtinute
ın a ¸
ˆ format XML vor fi procesate ¸i transformate ˆ
ın s ıntr-un tabel HTML a c˘rui
a
elemente vor fi adnotate RDFa. R˘spunsul obtinut ˆ urma unei interog˘ri ofer˘
a ¸ ın a a
informatii relevante cu privire la ce coloane sunt returnate (dac˘ privim RDF-ul
¸ a
ca o tabela, iar SPARQL ca SQL), ¸i informatiile ˆ sine. R˘spunsul obtinut cu
s ¸ ın a ¸
ajutorul libr˘riei arat˘ astfel:
a a
<sparql xmlns="http://www.w3.org/2005/sparql-results#">
<head>
<variable name="bill" />
10. 10
<variable name="person" />
<variable name="name" />
</head>
<results ordered="false" distinct="false">
<result>
<binding name="bill">
<uri>tag:govshare.info,2005:data/us/congress/108/bills/s1024</uri>
</binding>
<binding name="person">
<uri>tag:govshare.info,2005:data/us/congress/people/C001041</uri>
</binding>
<binding name="name">
<literal>Hillary Clinton</literal>
</binding>
</result>
<result>
<binding name="bill">
<uri>tag:govshare.info,2005:data/us/congress/108/bills/s1024</uri>
</binding>
<binding name="person">
<uri>tag:govshare.info,2005:data/us/congress/people/C000880</uri>
</binding>
<binding name="name">
<literal>Michael Crapo</literal>
</binding>
</result>
<result>
<binding name="bill">
<uri>tag:govshare.info,2005:data/us/congress/108/bills/s1024</uri>
</binding>
<binding name="person">
<uri>tag:govshare.info,2005:data/us/congress/people/L000174</uri>
</binding>
<binding name="name">
<literal>Patrick Leahy</literal>
</binding>
</result>
</results>
</sparql>
Dup˘ adnot˘rile RDFa un XML rezultat ˆ urma unei interogˆri ˆ punctul
a a ın a ın
terminal SPARQL oferit de dpbedia, asem˘n˘tor XML-ului de mai sus, va ar˘ta
a a a
astfel:
<table xmlns:rdf="http://purl.org/dc/terms/"
xmlns:ale="http://localhost"
about="SELECT * WHERE { ?x ?y ?z. } LIMIT 1">
11. 11
<tr>
<th property="rdf:identifier">x</th>
<th property="rdf:identifier">y</th>
<th property="rdf:identifier">z</th>
</tr>
<tr about="ale:row0>
<td property="ale:x"
resource="http://dbpedia.org/resource/Elizabeth_Peabody__Teacher">
http://dbpedia.org/resource/Elizabeth_Peabody__Teacher
</td>
<td property="ale:y"
resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#type">
http://www.w3.org/1999/02/22-rdf-syntax-ns#type
</td>
<td property="ale:z"
resource="http://www.w3.org/2002/07/owl#Thing">
http://www.w3.org/2002/07/owl#Thing
</td>
</tr>
</table>
3.2 C˘utare
a
Serviciul de c˘tare folose¸te clasa Site Crawler pentru a parcurge mai multe
a s
pagini ˆ c˘utare de noi leg˘turi.
ın a a
Fig. 1. Serviciul de search
12. 12
[WebMethod]
public String FindEndPoints(Int32 depth)
{
String path = Server.MapPath("~FilesEndpoints.txt") ;
Site_Crawler sc = new Site_Crawler(depth, path);
sc.FindPoints();
sc.SaveToCSV();
Hashtable ht = new Hashtable();
ht = sc.Sparql();
String str = "";
foreach (DictionaryEntry de in ht)
{
str += de.Value.ToString() + "n";
}
return str;
}
3.3 Interogare
Serviciul de interogare folose¸te clasa Interogate pentru a obtine rezultatul unei
s ¸
interog˘ri SPARQL. A¸teapt˘ ca parametri de intrare adresa la care se g˘se¸te
a s a a s
punctul terminal SPAQRL ¸i interogarea care se dore¸te a fi executat˘.
s s a
[WebMethod]
public String OneQuery(String url, String select)
{
String result = "";
Hashtable ht = new Hashtable();
SparqlQuery sq = new SparqlQuery(ht, select);
result = sq.RunSparql(url);
return result;
}
3.4 Pinging
Serviciul de pinging folose¸te aceea¸i clas˘ ca mai sus, avˆnd ca parametru de
s s a a
intrare doar adresa la care se g˘se¸te punctul terminal SPARQL.
a s
[WebMethod]
public String IsUp(String url)
{
String result = "";
String select = "SELECT * WHERE { ?x ?q ?z . } LIMIT 1";
SparqlQuery sq = new SparqlQuery(new Hashtable(), select);
try
{
13. 13
Fig. 2. Serviciul de query
String response = sq.RunSparql(url);
result = "OK";
}
catch (System.Net.WebException)
{
result = "FAILED";
}
return result;
}
4 Directii de dezvoltare
¸
Algoritmul de descoperire a punctelor terminale SPARQL poate fi ˆ ımbun˘t˘¸it
a at
prin utilizarea unor algoritmi de calcul paralel. Timpul de executie al algorit-
¸
mului ˆ cazul ˆ care adˆncimea depa¸e¸te num˘rul 7 nu poate fi aproximat.
ın ın a s s a
Nu exist˘ nici o rulare a aplicatiei ˆ conditii de acest tip. O alt˘ ˆ
a ¸ ın ¸ a ımbun˘t˘¸ire
a at
ce poate fi adus˘ proiectul o poate reprezinta o aplicatie web care s˘ reuneasc˘
a ¸ a a
toate serviciile prezentate ˆ aceast˘ lucrare.
ın a
14. 14
Fig. 3. Serviciul de pinging ¸i rezultat
s
References
1. SemWeb http://razor.occams.info/code/semweb/
2. Jonathan Wood, ”Parsing HTML Tags in C#” 2010 (articolul se poate g˘si la adresa
a
http://www.codeproject.com/Articles/57176/Parsing-HTML-Tags-in-Csharp.aspx)