Praca wstawiona.

This commit is contained in:
siulkilulki 2018-06-22 07:28:04 +02:00
parent e0e7165f83
commit 2b1eedf4d1
8 changed files with 644 additions and 137 deletions

View File

@ -1,4 +1,10 @@
\chapter*{Abstract}
todo
The thesis presents the process of creating a system for extracting information
about opening hours
of holy masses. The methods of collecting data of Polish parishes are being
described, especially the process of creating spiders. Then two methods are shown
for the extraction of opening hours of masses: a rule-based method and
machine learning-based method. More attention is devoted to machine
learning-based method that uses a text classifier.
\textbf{Key words:} information extraction
\textbf{Key words:} information extraction, web spidering, text classification

View File

@ -1,66 +1,98 @@
@ARTICLE{Bootstrap,
author = {Daniel Waegel},
title = {A Survey of Bootstrapping Techniques in Natural Language Processing},
journal = {Department of Computer Science,
University of Delaware, Literature Survey Reports},
year = {2013}
}
@ARTICLE{Hearst,
author = {Marti Hearst },
title = {Automatic Acquisition of Hyponyms from Large Text Corpora.},
journal = {Proc. of the
Fourteenth International Conference on Computational Linguistics, Nantes, France.},
year = {1992}
}
@inproceedings{genetic,
title={Learning text patterns using separate-and-conquer genetic programming},
author={Bartoli, Alberto and De Lorenzo, Andrea and Medvet, Eric and Tarlao, Fabiano},
booktitle={European Conference on Genetic Programming},
pages={16--27},
year={2015},
organization={Springer}
}
@article{ramped,
title={Genetic programming as a means for programming computers by natural selection},
author={Koza, John R},
journal={Statistics and computing},
volume={4},
number={2},
pages={87--112},
year={1994},
publisher={Springer}
}
@article{gus,
title={Rocznik statystyczny Rzeczypospolitej Polskiej 2017},
author={Dominik Rozkrut i in},
author={Dominik Rozkrut},
journal={GUS},
volume={T. LXXVII},
pages={194--195},
year={2016}
year={2017}
@Comment publisher={}
}
@misc{beautiful_soup,
title = {BeautifulSoup},
note = {Crummy.org},
title = {Strona internetowa {BeautifulSoup}},
key = {BeautifulSoup},
howpublished={\url{https://www.crummy.com/software/BeautifulSoup/}}
note = "Crummy.org [Online; dostęp 22.06.2018]"
}
@misc{expotential_backoff}
@misc{google_api}
@misc{text_search}
@misc{place_detail}
@misc{jsonline}
@misc{binaryornot}
@misc{html2text}
@misc{markdown}
@misc{scrapy}
@misc{expotential_backoff,
title = "Exponential backoff --- {Wikipedia}{,} The Free Encyclopedia",
year = "2018",
howpublished = "\url{https://en.wikipedia.org/w/index.php?title=Exponential_backoff&oldid=830252246}",
note = "[Online; dostęp 22.06.2018]"
}
@misc{google_api,
title = "{Google Places API}",
howpublished = "\url{https://developers.google.com/places/web-service/intro}",
note = "[Online; dostęp 22.06.2018]"
}
@misc{text_search,
title = "{Google Place Search}",
howpublished = "\url{https://developers.google.com/places/web-service/search}",
note = "[Online; dostęp 22.06.2018]"
}
@misc{place_detail,
title = "{Google Place Details}",
howpublished = "\url{https://developers.google.com/places/web-service/details}",
note = "[Online; dostęp 22.06.2018]"
}
@misc{jsonline,
title = "{Dokumentacja formatu JSON Lines}",
howpublished = "\url{jsonlines.org}",
note = "[Online; dostęp 22.06.2018]"
}
@misc{html2text,
title = "{Repozytorium html2text}",
howpublished = "\url{https://github.com/Alir3z4/html2text}",
note = "[Online; dostęp 22.06.2018]"
}
@techreport{markdown, author = {S. Leonard}, title = {The text/markdown Media Type}, howpublished = {Internet Requests for Comments}, type = {RFC}, number = {7763}, year = {2016}, month = {March}, issn = {2070-1721}, publisher = {RFC Editor}, institution = {RFC Editor}, }
@misc{fingerprintjs2,
title = "{Dokumentacja fingerprintjs2}",
howpublished = "\url{https://github.com/Valve/fingerprintjs2/blob/master/README.md}",
note = "[Online; dostęp 22.06.2018]"
}
@misc{softmax,
title = "Softmax function --- {Wikipedia}{,} The Free Encyclopedia",
year = "2018",
howpublished = "\url{https://en.wikipedia.org/w/index.php?title=Softmax_function&oldid=843761006}",
note = "[Online; dostęp 22.06.2018]"
}
@article{scrapy,
author = {Myers, Daniel and McGuffee, James W.},
title = {Choosing Scrapy},
journal = {J. Comput. Sci. Coll.},
issue_date = {October 2015},
volume = {31},
number = {1},
month = oct,
year = {2015},
issn = {1937-4771},
pages = {83--89},
numpages = {7},
url = {http://dl.acm.org/citation.cfm?id=2831373.2831387},
acmid = {2831387},
publisher = {Consortium for Computing Sciences in Colleges},
address = {USA},
}
@article{word2vec,
author = {Xin Rong},
title = {word2vec Parameter Learning Explained},
journal = {CoRR},
volume = {abs/1411.2738},
year = {2014},
url = {http://arxiv.org/abs/1411.2738},
archivePrefix = {arXiv},
eprint = {1411.2738},
timestamp = {Wed, 07 Jun 2017 14:43:03 +0200},
biburl = {https://dblp.org/rec/bib/journals/corr/Rong14},
bibsource = {dblp computer science bibliography, https://dblp.org}
}
@misc{fasttext,
Author = {Armand Joulin and Edouard Grave and Piotr Bojanowski and Tomas Mikolov},
Title = {Bag of Tricks for Efficient Text Classification},
Year = {2016},
Eprint = {arXiv:1607.01759},
@article{parallel,
title = {GNU Parallel - The Command-Line Power Tool},
author = {O. Tange},

View File

@ -1 +1 @@
<mxfile userAgent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.79 Safari/537.36" version="8.7.10" editor="www.draw.io" type="device"><diagram id="cb6c6256-43c7-094e-4ab5-cf55f2e6a3c1" name="Page-1">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</diagram></mxfile>
<mxfile userAgent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.79 Safari/537.36" version="8.7.10" editor="www.draw.io" type="device"><diagram id="cb6c6256-43c7-094e-4ab5-cf55f2e6a3c1" name="Page-1">7R1dc6M48te46u5hKfSJeJzkZnavbqZqame3dvfeiE1sYmJ8mIzj/PqTDMJIyI5sC8KQ9VRNjJAR9He3upsJun18/jmP1osv2SxOJ9CfPU/QvyYQAkAY/yNGdtWIj3A5Ms+TWTV2GPiWvMRyYjX6lMzijTKxyLK0SNbq4DRbreJpoYxFeZ5t1Wn3Waquuo7mcWvg2zRK26N/JLNiUY4y4h/Gf4mT+UKuDPzqzF00Xc7z7GlVrTeB6H7/KU8/RvJa1fzNIppl28YQ+jhBt3mWFeW3x+fbOBXAlWArf/fpyNn6vvN4VVj9AMHyJ9+j9CmW97y/s2InobF/nlj8AkzQzXaRFPG3dTQVZ7ecAPjYonhMq9ObIs+W8W2WZjkfWWUrPu3mPklTOSRAQsQ/MZ6tigr7APPjKE3mK34w5bcf88k37eepHvF7nBfxc2Ooer6f4+wxLvIdn1KdDcsfVKQYoAry2wNeAa3GFg2cQiLpqaKleX3lAzz5lwqkZvAyOnboEknJFXxpG7wIGsDLfAfQDd4bdKEP7cBbC6Rr4AvY6/CNV7MPQuCKB0+jzSaZqiCNn5PiT/7d90h19Fd1ZhZtFjVixMHXqOCAW+1HxIOegOAme8qnUlZXPFZE+TyW00g5Fs8UOd+GcwOOxABGOZbHaVQk31XtYAJttcLXLOF3XKMRAKCgkQANO+XzVL9qimv9QlS9EKbahUogtC60x3T92HbIh2dxl++Iu0plqXIX64i7AqJCEwRt7jIxF3TBW3D8qgGpwgthW9XrBMA20uvHBjCQCrACMGOhQTugNoBDJ/AdveUImErAODAYN9hAwE7g64/eukFUhy+wFRChCwCT9wbgAJE2AaPOCBiPHb66hiNhWwAfIWAHzmUIxg5fhLECX5P7A4KuLAg2evmgKziT824SD06cdwvp8KpzueKL/tk8EM7lwdXcO54Nt7M848rxrCOTDcez0tkD8Tt1+QQJVC9h63fSgHk+OXw0tgy0y7rzQiUfN6gkmuXxRsDwKU9LJEX3SXKCMy1c07YXCqfTFsfyMzN6Rwl1FdxhKhilRd2Ubib/U3f6L2E/E/fRtKgEjwJK+r+nTJ74abMXSR/4BIDWz4eT/Ntc/F1HD5NbPGFkyaesopetWFPcq8Da5BZNbtC2ibVyTX635bLlRZwicxbF7N6ITDpl8d29G2RCXzO1DL5uV7gMLDwFIZG+VYdZXiyyebaK0o+H0RsVxoqUraXwXZpNl78tklU5/ClJ5aSHuCh2lb6KnoqMDx2W+Zxl64a8dSF8SVv2ykDgq8LXWqraIsBkKDhnJo2Dfv/18xj5iCBVKPbJR6aInAs0xksOsmhZcHhBf57NXjj/QP9x87IbD970bTbSp/zrCG8CppA/fzEeNCEZYpE2h1QVfeDJFJDtjL9GgzGmbfnIoG8fGAs7whiHZJHvf55nq1qNRelqN12MB3UEq7oMkR6ZDbQ9Jze4W3JPfHefLKNx8ptuyIcyjNkL0mBHSBOe2K7piu36NR778ahR8HZOGEAG1J0bz6piVvJ7I5olI11+O9LlyqWq6FxxqapnGEg8C2jpMBfnUSCNyVvpMg7zKFzEOd+ULiQRNAljYPk1xBFd6PlWXdJFL0GDcRtYgf+G3gzoKlxQ6+feQzz9aGkda31qaUPcezT7CUhLDkSoR24wxEDHA1gtaIJwn4DtSszsVcPBDeC6IeYH/yhENOWf45E2evykVyfcJof2NePPwow7WIEeCZBqCfp+bSd+jfOEP4LIHtij6yh0m5aelJgDMfWwvqXNoHoJW1MPoyPSsoNN7K4Cn9EqK8owzFgsOj1kRmGfxoEp3PlDuWrQUAsRDop/Q5V9A/9S9gXqhbCe2uKOfaXE6UcDj0Xv6pzc674Fchh06a5yKWwzq6S1gXAr9ZkHQEBx4BPGuKhXUQqZJ88QGGIZ6rpAFXtI1AhjBgPCKNIIh99DwBkeBaGYRTrjc4t8T+uMxIbM/0vK/O4zEg0hXNukmH4ICuklFTK4eHYlnCb/SQA82vgEVlTCcRntGtPWYsLm+O3LAhtpM1Ko0Vx5wYsp0KImbNgGiMH+QMPKiQVYJRwahqcIx3pHoSKFmrCxpsYcyqmu8l3KrVyBijI3yZ/ckkl4s01EPDkMi55ix28TF+g1Ywm5rKw+zuiGtHhXjC4NlSans0Exuu5pkAs5WxcYgW+nWy7hbBcOqI0F0plJy9pUgYdl0mKsGQpqLQMJQg81Ppq1aUs0gV7xTzpTB7gr97RWB2MV+b0Gl7BFtd6wbTtsEPkDk/mY+ac8Seqf8iStkwRw4EGfspASIi4Hz1nEId+bEo6c5Iol8Tpb59F2vyH0roxCPWjVq1Eoi127CVqdsgucxR8M6n9g7h8kwKvFA+fiUG2hQVjo1ec4h9PLRMQrq1CormInI84NVlBfI2a9F1zbMjo1/+roBu5qJ7vgRJltIy63+JRmenI06TU/mcRshk0iisE7RJ0ZMW+Yn0xMtuYPJaKk1lQ8lGHFSLl4aAoPrccPOCk6rAu6tdZXDNn5J9fKIIbPk0Ha/KtlEHFohb9N4AWb2t0Ny8XW03FDuR139saQFsNhvnYhd9Y0GaXxJaXdQAjj9EafI9vr9CKXmV4XEBTtKiyzzssi8LultHnGYtroicG9xmeoC81g04+ms9grNcRnBiYAAhp6YeOjGgdEbztmHW0Vl62iMfu4iwOWP9fSCbTs64C5tVyog1TSN1ZQBstlYOFDDLxGOgtQTW9X6S4UMc9nDBNY/q8uErDONJKLTUeL3SU1Og27zm+kwzJ+211v4aVCTbuQZYLyuYJLr3lDlaSxrZFD4LRLpwtGbf7VgjEwGVrHybpqu6dQ5JlbLCrpgyv2Rgcm/jRMXZ4Mo+XW06CbdCwcqutI3rONLmjzryfF82xIS1JUtbWvkGLbzhwHKRJw0lOE1IWniEJV9xKstRV2RaY62fmnyRTpZO07JlOHrQpMQbBmX7g+QmIGagYDC4lh/9TGNCGBi41ppLcjBp1lKrFOSeickrefRImbRlzcs5QD1jVvSseDYbU3oFT1kyGAHkAoxKEPaOBDcqH84/rdCxl3ZygDhGJZwitXIVAUD3JiJSEEAdML7RzWx1mozR8gd0DrXNhrMwK5Vl9Vwr/89uXziIqE9bwP2GfpfOgAd8yEu//eJXFebYsnq/ssf4ymD6IDVHbAp332zr4RokUT82qoidJDK3OI5XF1YXFe4CmZRumHqsX5YzKb7VvStnqeq+3WHSAehmr6pyni7Bvwrmf3X4R3Bx1gBN73CNdQ/8du8/K0TGRShIvesU7wv3+X04DwT/Vy8h7xX1/YOeP/mwNpualTYq5pAjRSrKumDqAGcd8d2k3mjgu0/ydbbeN88yDSnvaIEB3YhWMkWnq8a4QjzYLuGeEOEt+MCP8g+j9MH85PcxslkgnRthMp8drvO+oQzQ7afBjR/LHsb/w3oo8YbVjWzfaC5s4a646u3kZvpdtrC4j6navnBeOPvq5pIpqGio/AVB7NEg4XmxeXntwxrUOl1+6zDzidFWv1k+zi5px6NmB3JdbAZTfft8m2qOXUgBNFMQEeCQCGrPyf6gkXwGucJVpmhHVC4CurhIF3WCMAejTVJVWZkkxV1VFKjoNyAG09IX9yZ6Vq8PWV/nf6yt2qppgeUU1BeOefjOFf/LqSfpu8G1v/nilcHCmnNxVRpkx2ySIDkVBIpRPg6w2hbYWQ1jmGBR3qLgddZByT1+RoMk2H28JGBTg0+lJNmsv3fvWqMNZZYjsApi4VTuJXsnTvb0+3Jg+oig3Sp6fr4iWRRkR/Eq//0cPT7xjNRE/1lKKrFzQjC1/nLIvO6j3Hx3RGF+851nq8UNa29kyvOUaBA+i6eIeWkYl+jedPwmxnkHOS0GjNKGHtI+SqyT85772Do+Q2LRuPMtBrmNimyd8V7MZ569P+Y0aRJbu1oGmA+VEAA92o8Q3izJF3xQ/zTPDFwZrhAFp8yWaxmPF/</diagram></mxfile>

View File

@ -1,4 +1,4 @@
\documentclass[a4paper, 12pt, twoside]{report}
\documentclass[a4paper, 12pt, twoside, reqno]{report}
\input{pakiety.tex}
\input{ustawienia.tex}
@ -51,14 +51,19 @@
\newpage\null\thispagestyle{empty}\newpage
% spis ilustracji:
%\newpage
%\listoffigures
%\addcontentsline{toc}{chapter}{Spis ilustracji}
\newpage
\listoffigures
\addcontentsline{toc}{chapter}{Spis rysunków}
% spis algorytmów:
\newpage
\listofalgorithms
\addcontentsline{toc}{chapter}{Spis algorytmów}
% spis tabel:
%\newpage
%\listoftables
%\addcontentsline{toc}{chapter}{Spis tabel}
\newpage
\listoftables
\addcontentsline{toc}{chapter}{Spis tabel}
%bibliografia

View File

@ -5,6 +5,12 @@
\usepackage{makeidx} % indeks
\usepackage[pdftex]{graphicx} % zalaczanie grafiki
\usepackage{tikz} % grafika wektorowa
\usepackage[
left = „,
right = ”,
leftsub = «,
rightsub = »
]{dirtytalk} % cudzysłówy dla różnych języków \say{nic} --> "nic"
\usepackage{setspace} % interlinia
@ -24,6 +30,7 @@
\usepackage{floatflt} % ladne oplywanie obrazkow tekstem
\usepackage{url} % url w bibliografii
\usepackage{amsmath}
\usepackage{mathtools}
\usepackage{amsthm}
\usepackage[section]{placeins} %wymusza by obrazek był w obrębie sekacji a nie poza nią

View File

@ -1,13 +1,12 @@
\chapter{Podstawy teoretyczne i/lub spis pojęć}
\chapter{Ekstrakcja godzin rozpoczęcia mszy świętych}
\section{Ogólny zarys systemu}
Architektura systemu ekstrakcji godzin rozpoczęcia mszy świętych została
przedstawiona na rysunku \ref{pic:architektura}. W tym podrozdziale zostanie ona
przedstawiona na rysunku \ref{pic:architektura}. W niniejszym podrozdziale zostanie ona
krótko opisana. Szczegółowy opis poszczególnych komponentów znajduje się w
kolejnych podrozdziałach.
podrozdziałach \ref{sub:zbieranie_informacji} - \ref{sub:klasyfikacja}.
System zaczyna działanie od zebrania jak największej ilości danych (nazwa parafii, adres, diecezja
itd.) o polskich parafiach ze strony deon.pl. Następnie wysyła zapytania do interfejsu API
itd.) o polskich parafiach ze strony \url{deon.pl}. Następnie wysyła zapytania do interfejsu API
Google w
celu znalezienia adresów internetowych parafii.
Dla każdej parafii, dla której udało się znaleźć adres URL, pobierane są wszystkie
@ -16,7 +15,7 @@ podstrony w odległości\footnote{Zakładamy, że sieć jest grafem, zatem odleg
Z dużej liczby stron parafialnych, za pomocą reguł wyodrębnione zostają
te, na których z dużym prawdopodobieństwem znajdują się godziny mszy świętych.
Następnie godziny zostają wydobyte ekstraktorem
Następnie godziny zostają wydobyte ekstraktorem godzin
o bardzo niskiej precyzji i bardzo wysokiej wartości pokrycia.
Każda godzina wraz z kontekstem, w jakim się znajduje, trafia do anotatora.
Tam jest oznaczana jako poprawna lub niepoprawna godzina mszy
@ -24,8 +23,8 @@ Tam jest oznaczana jako poprawna lub niepoprawna godzina mszy
godziny mszy świętych” rozumiemy godziny, które nie są
godzinami rozpoczęcia mszy świętych.}.
Regułowy ekstraktor mszy świętych o bardzo wysokiej precyzji znajduje poprawne
godziny mszy świętych i dołącza je do zanotowanych danych.
Dodatkowo w celu wyrównania
godziny mszy świętych i dołącza je do zaanotowanych danych.
Co więcej, w celu wyrównania
klas z nieodfiltrowanego zbioru stron parafialnych wylosowane zostają niepoprawne godziny mszy świętych.
Zebrane dane zostają użyte do wytrenowania klasyfikatora godzin opartego na
płytkich sieciach neuronowych.
@ -53,6 +52,7 @@ znalezionych przez ekstraktor godzin do następujących klas:
\clearpage
\section{Zbieranie informacji o parafiach}
\label{sub:zbieranie_informacji}
\begin{figure}[htb]
\center
@ -61,10 +61,10 @@ znalezionych przez ekstraktor godzin do następujących klas:
\label{pic:pajak_nazw_parafii}
\end{figure}
Na rysunku \ref{pic:pajak_nazw_parafii} został przedstawiony fragment architektury
systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w tym podrozdziale.
systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w niniejszym podrozdziale.
Dane zostały zebrane z serwisu internetowego deon.pl, który zawiera 10130 parafii.
Jest to większość polskich parafii, ponieważ według
Są to prawie wszystkie polskie parafie, ponieważ według
danych statystycznych GUS\cite{gus} z 2016 roku w Polsce było
10255 parafii.
@ -91,14 +91,14 @@ Dla każdej parafii zebrano:
Św. Trójcy & Paszowice & Paszowic... & legnicka & Jawor & dolnośląskie\\
\\ [-1.5ex]
\end{tabular}
\caption{Fragment zebranych danych.}
\caption{Fragment danych zebranych przez pająka nazw i adresów parafii.}
\label{dane_tab}
\end{table}
Do wydobycia danych użyto skryptu w języku Python, który korzystał z parsera
HTML z biblioteki \textit{Beautiful Soup}\cite{beautiful_soup}. Przy wysyłaniu zapytań do serwisu deon.pl zastosowano
algorytm \textit{Expotential Backoff}\cite{expotential_backoff}, który
przedstawia się następująco:
algorytm \textit{Expotential Backoff}\cite{expotential_backoff}
(patrz algorytm \ref{alg:backoff}).
\begin{algorithm}
\setstretch{1.2}
@ -138,7 +138,7 @@ Dla każdej parafii zebrano:
Algorytm \ref{alg:backoff} uodparnia skrypt na przejściowe problemy z połączeniem i
zapobiega zbyt częstemu wysyłaniu zapytań do serwisu. Dla przykładu załóżmy,
że dany serwis jest obciążony i nie daje sobie rady z przetwarzaniem zapytań.
że dany serwis jest obciążony i odpowiada na zapytanie z dużym opóźnieniem.
Wtedy algorytm \textit{Expotential Backoff} przy każdym kolejnym niepowodzeniu
będzie czekał coraz dłużej, zanim wyśle kolejne zapytanie. W ten sposób nie
będzie niepotrzebnie obciążał serwisu.
@ -153,14 +153,14 @@ Dla każdej parafii zebrano:
\end{figure}
Na rysunku \ref{pic:pajak_url} został przedstawiony fragment architektury
systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w tym podrozdziale.
systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w niniejszym podrozdziale.
\subsubsection{Pierwsze próby}
Do wyszukiwania adresów URL parafii próbowano wykorzystać wyszukiwarki takie jak
Google i DuckDuckGo. Automatycznie wysyłano zapytanie złożone z konkatenacji
nazwy parafii, jej miejscowości i ulicy, na której się znajduje. Wyszukiwarka Google dawała
zadowalające wyniki, jednak po kilkunastu zapytaniach blokowała adres IP. W
dodatku w warunkach użytkowania serwisu i w pliku \textit{robots.txt} Google zabrania
zadowalające wyniki, jednak po kilkunastu zapytaniach blokowała adres IP.
Ponadto, w warunkach użytkowania serwisu i w pliku \textit{robots.txt} Google zabrania
korzystania z pająków na ich wyszukiwarce.
Wyszukiwarka DuckDuckGo nie blokowała adresu IP, ale zabraniała indeksowania w pliku \textit{robots.txt} i słabo radziła sobie z polskimi
zapytaniami. W obu przypadkach powyższa metoda stwarzała kolejny problem do
@ -171,12 +171,12 @@ Po wielokrotnych próbach poszukiwań znaleziono klucz do rozwiązania problemu
wyszukiwania adresów URL, jakim jest
\textit{Google Places API}\cite{google_api}. Serwis \textit{Text Search}\cite{text_search} pozwala na wyszukanie miejsca
danego obiektu na
podstawie jego nazwy. Ponadto mając już wyszukany dany obiekt i jego
podstawie jego nazwy. Ponadto, mając już wyszukany dany obiekt i jego
identyfikator można odpytać serwis \textit{Place Detail}\cite{place_detail}, aby wyciągnąć więcej
szczegółów o danym miejscu. Między innymi można otrzymać adres URL danego obiektu.
Jedynym minusem jest ograniczenie liczby zapytań do 1000 na 24 godziny. W
dodatku każde zapytanie do serwisu \textit{Text Search} traktowane jest jak 10
dodatku, każde zapytanie do serwisu \textit{Text Search} traktowane jest jak 10
zapytań. Podając swoją kartę płatniczą, można zwiększyć limit
zapytań do 150 000 na 24 godziny. Karta płatnicza jest potrzebna Google do
identyfikacji osoby. Żadna opłata nie jest pobierana za korzystanie z interfejsu
@ -193,10 +193,10 @@ przypadku brany jest adres URL pierwszego obiektu z listy wyników.
Najczęściej jednak oba obiekty należą do tej samej parafii, więc mają taki sam
adres internetowy. Taki przypadek przedstawia rysunek \ref{pic:text_search}.
Serwis \textit{Text Search} zwraca dużo danych w formacie JSON, które
ciężko przedstawić w przejrzystej postaci.
trudno jest przedstawić w przejrzystej postaci.
Dla
czytelności na rysunku \ref{pic:text_search} pokazano zrzuty ekranu z wyszukiwarki \textit{Google Maps},
które odpowiadają rezultatowi, jaki otrzymano by, korzystając z serwisu
które odpowiadają rezultatowi, jaki otrzymano, korzystając z serwisu
\textit{Text Search}.
\noindent Powyższą metodą udało się zebrać adresy URL dla ok. 5600 parafii.
@ -222,7 +222,7 @@ które odpowiadają rezultatowi, jaki otrzymano by, korzystając z serwisu
Na rysunku \ref{pic:pajak_parafii_general} został przedstawiony fragment architektury
systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w tym podrozdziale.
systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w niniejszym podrozdziale.
Pająk został napisany przy użyciu biblioteki \textit{Scrapy}\cite{scrapy}.
Punktem startowym jest pojedynczy adres URL parafii podawany na wejście
@ -235,17 +235,17 @@ asynchronicznie wysłać wiele zapytań do serwera i odbierać wiele odpowiedzi
Pająk składa się z następujących komponentów:
\begin{description}
\item [Silnik] -- odpowiada za kontrolę przepływu danych i komunikację między komponentami.
\item [Dyspozytor] -- otrzymuje żądania od silnika, kolejkuje je i na
prośbę silnika odsyła z powrotem.
\item [Dyspozytor] -- otrzymuje żądania od \textit{silnika}, kolejkuje je i na
prośbę \textit{silnika} odsyła z powrotem.
\item [Downloader] -- odpowiada za pobieranie stron parafialnych i
przekazywanie ich silnikowi.
przekazywanie ich \textit{silnikowi}.
\item [Procesor danych] -- zajmuje się końcową obróbką i zapisem danych.
\item [Spider]\footnote{Użyto angielskiej nazwy, aby rozróżnić
\textit{spider'a} (komponent pająka), od pająka (cały program
odpowiedzialny za indeksowanie stron parafialnych).}
- definiuje sposób, w jaki pobierać dane, między innymi jak parsować stronę i za jakimi
linkami podążać.
\item [Spider middleware] -- programy pośredniczące między silnikiem, a
\item [Spider middleware] -- programy pośredniczące między \textit{silnikiem}, a
\textit{spider'em}. Odpowiedzialne są za dodatkowe przetwarzanie danych wyjściowych
(dane parafialne i żądania) i wejściowych (odpowiedzi) \textit{spider'a}.
\item [Downloader middleware] -- programy pośredniczące między silnikiem, a
@ -256,7 +256,7 @@ Pająk składa się z następujących komponentów:
\subsection{Przepływ danych}
Przepływ danych kontrolowany jest przez
silnik i wygląda następująco\footnote{Diagram i opis wzorowany jest na
\textit{silnik} i ma postać przedstawioną na rysunku \ref{pic:scrapy_data_flow}\footnote{Diagram i opis wzorowany jest na
dokumentacji znajdującej się pod linkiem https://doc.scrapy.org/en/latest/topics/architecture.html.}:
\begin{figure}[tbh]
@ -265,34 +265,33 @@ silnik i wygląda następująco\footnote{Diagram i opis wzorowany jest na
\caption{Silnik kontrolujący przepływ danych przez komponenty pająka.}
\label{pic:scrapy_data_flow}
\end{figure}
\begin{enumerate}
\item Silnik otrzymuje od \textit{spider'a} żądanie pobrania początkowej strony danej
\item \textit{Silnik} otrzymuje od \textit{spider'a} żądanie pobrania początkowej strony danej
parafii (najczęściej jest to strona główna parafii).
\item Silnik oddaje żądania dyspozytorowi, który kolejkuje je do dalszego
przetwarzania oraz pyta dyspozytora o żądania gotowe do przekazania \textit{downloader'owi}.
\item Dyspozytor zwraca silnikowi następne żądania.
\item Silnik wysyła żądania do \textit{downloader'a}. Zanim żądania dotrą do
\item \textit{Silnik} oddaje żądania \textit{dyspozytorowi}, który kolejkuje je do dalszego
przetwarzania oraz pyta \textit{dyspozytor} o żądania gotowe do przekazania \textit{downloader'owi}.
\item \textit{Dyspozytor} zwraca \textit{silnikowi} następne żądania.
\item \textit{Silnik} wysyła żądania do \textit{downloader'a}. Zanim żądania dotrą do
\textit{downloader'a}, przetwarzane są przez \textit{downloader middleware}.
\item \textit{Downloader} pobiera stronę parafialną i umieszcza ją w odpowiedzi, którą
przesyła silnikowi. Zanim odpowiedź dotrze do silnika, przetwarzana jest przez
przesyła \textit{silnikowi}. Zanim odpowiedź dotrze do \textit{silnika}, przetwarzana jest przez
\textit{downloader middleware}.
\item Silnik otrzymuje odpowiedź od \textit{downloader'a} i przekazuje ją \textit{spider'owi} do
\item \textit{Silnik} otrzymuje odpowiedź od \textit{downloader'a} i przekazuje ją \textit{spider'owi} do
dalszego przetwarzania. Zanim odpowiedź trafi, do \textit{spider'a} przetwarzana jest
przez \textit{spider middleware}.
\item \textit{Spider} przerabia odpowiedź i zwraca dane strony parafialnej silnikowi. Zanim dane
trafią, do silnika przechodzą przez \textit{spider middleware}. Dodatkowo \textit{spider}
\item \textit{Spider} przetwarza odpowiedź i zwraca dane strony parafialnej \textit{silnikowi}. Zanim dane
trafią do \textit{silnika}, przechodzą przez \textit{spider middleware}. Dodatkowo \textit{spider}
wysyła żądania z nowymi stronami parafialnymi do pobrania.
\item Silnik wysyła zebrane dane do procesora danych, który zapisuje je do
\item \textit{Silnik} wysyła zebrane dane do \textit{procesora danych}, który zapisuje je do
pliku. Następnie przekazuje nowe żądania do zakolejkowania
dyspozytorowi.
\textit{dyspozytorowi}.
\end{enumerate}
% \vspace*{-20mm}
Cały proces trwa dopóty, dopóki są nowe żądania do przetworzenia.
\subsection{Sprawdzanie typu odpowiedzi}
Podczas indeksowania ważne jest rozpoznawanie typu pobieranych danych. W przypadku
indeksowania stron parafialnych interesują nas wyłącznie dane tekstowe. Należy
indeksowania stron parafialnych przedmiotem zainteresowania są wyłącznie dane tekstowe. Należy
zatem zadbać o to, aby nie pobierać danych binarnych takich jak np. video, audio
i obrazy.
@ -306,12 +305,14 @@ następujących kryteriach:
rozpoznać po nazwie pliku lub adresie URL).
\end{itemize}
Powyższy schemat postępowania jest skuteczny, jeśli serwisy internetowe zwracają
poprawne odpowiedzi. Niestety niektóre strony parafialne potrafią zwracać
odpowiedzi, które nie są zgodne z rozdziałem 3.1 z dokumentu RFC7231\cite{RFC7231}.
poprawne odpowiedzi. Niestety, niektóre strony parafialne zwracają
odpowiedzi, które nie są zgodne z rozdziałem 3.1 z dokumentu
RFC7231\cite{RFC7231}\footnote{RFC to zbiór technicznych dokumentów w formie
memorandum opisujących protokoły związane z Internetem i sieciami komputerowymi.}.
Dla przykładu strona potrafi zwrócić \mintinline{bash}{Content-Type: text/html}
w nagłówku, a w ciele binarną
w nagłówku, a w ciele -- binarną
zawartość np. film. Tego rodzaju anomalie są wykrywane i eliminowane.
\enlargethispage{2\baselineskip}
\enlargethispage{3\baselineskip}
Stosując algorytm \ref{alg:binaryornot}, można określić typ zawartości
ciała odpowiedzi.
@ -355,7 +356,7 @@ ciała odpowiedzi.
\end{algorithm}
Algorytm \ref{alg:binaryornot} analizuje zawartość ciała odpowiedzi w celu
stwierdzenia czy jest ona binarna, czy nie.
stwierdzenia, czy jest ona binarna, czy nie.
W linii 6 za znaki kontrolne uznano
wszystkie znaki kontrolne ze zbioru C0\footnote{C0 to znaki kontrolne z kodu
ASCII o kodach od 0 do 32 i o kodzie 127.} i C1\footnote{C1 to znaki kontrolne
@ -377,7 +378,8 @@ Warto zwrócić uwagę na linię 10. Współczynnik
\mintinline{python}{control_char_ratio}
oznacza procent znaków kontrolnych w pierwszych 1024 bajtach pliku.
Jeśli współczynnik \mintinline{python}{control_char_ratio} jest większy niż
$0,3$, to plik jest uznawany za binarny. Wartość $0,3$ została wzięta z
$0,3$, to plik jest uznawany za binarny. Wartość $0,3$ została przyjęta z
rozwiązania z
kodu\footnote{Kod znajduje się pod linkiem \url{https://github.com/Perl/perl5/blob/v5.27.11/pp\_sys.c\#L3605-L3665}. Wartość 0,3 występuje w linii 3661.}
źródłowego języka Perl, który między innymi zajmuje się rozpoznawaniem plików
binarnych. Natomiast współczynnik \mintinline{python}{high_ascii_ratio} oznacza
@ -414,7 +416,7 @@ Załóżmy, że serwer potrzebuje
zdefiniowana w algorytmie \ref{alg:throttling}.} sekund, aby odpowiedzieć pająkowi. Jeśli pająk chce
mieć przetworzone równolegle
\mintinline{python}{target_concurrency}\footnote{Stała
\mintinline{python}{target_concurrency} została zdefiniowana w algorytmie \ref{alg:throttling}.}zapytań to powinien
\mintinline{python}{target_concurrency} została zdefiniowana w algorytmie \ref{alg:throttling}.}zapytań, to powinien
wysyłać każde zapytanie co \mintinline{python}{latency/target_concurrency}
sekund.
@ -511,7 +513,7 @@ indeksowania stron parafialnych.
\subsection{Organizacja danych}
\enlargethispage{1\baselineskip}
Dane zbierane przez pająka zapisywane są do pliku w formacie JSONL. Format JSONL charakteryzuje się tym, że w każdej linii pliku
Dane zbierane przez pająka zapisywane są do pliku w formacie JSONL\cite{jsonline}. Format JSONL charakteryzuje się tym, że w każdej linii pliku
znajduje się poprawny obiekt JSON.
Dla
każdej parafii pobrane dane zapisywane są w oddzielnym pliku. W każdej linii
@ -520,7 +522,7 @@ Taki sposób organizacji danych przynosi szereg korzyści takich jak:
\begin{enumerate}
\item wygodne przetwarzanie równoległe,
\item łatwa obróbka danych za pomocą narzędzi Uniksowych,
\item mniejszy rozmiar pliku w porównaniu do zwykłego formatu \textit{JSON}.
\item mniejszy rozmiar pliku w porównaniu do zwykłego formatu JSON.
\end{enumerate}
\noindent Dla każdej strony parafialnej zapisywane są następujące informacje:
@ -543,7 +545,7 @@ Taki sposób organizacji danych przynosi szereg korzyści takich jak:
\end{figure}
Na rysunku \ref{pic:html2text} został przedstawiony fragment architektury
systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w tym podrozdziale.
systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w niniejszym podrozdziale.
Do konwersji z formatu HTML na format tekstowy wykorzystano bibliotekę \mintinline{bash}{html2text}\cite{html2text}
pierwotnie rozwijaną przez Aarona Schwartza.
@ -570,7 +572,7 @@ konwersji i jest bardzo łatwa w modyfikacji.
\label{pic:general_ekstraktor}
\end{figure}
Na rysunku \ref{pic:html2text} został przedstawiony fragment architektury
systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w tym podrozdziale.
systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w niniejszym podrozdziale.
Ekstraktor godzin służy do znajdowania bardzo ogólnych ciągów znaków mogących
być godzinami rozpoczęcia mszy świętych. Został napisany z myślą, aby miał
@ -603,7 +605,7 @@ Ekstraktor wraz
\label{pic:filtrowanie}
\end{figure}
Na rysunku \ref{pic:filtrowanie} został przedstawiony fragment architektury
systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w tym podrozdziale.
systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w niniejszym podrozdziale.
Filtr stron parafialnych ma za zadanie odnaleźć strony parafialne, na których z
dużym prawdopodobieństwem znajdują się godziny mszy świętych. Taki zabieg jest
@ -687,6 +689,7 @@ W algorytmie \ref{alg:has_mass} warto zwrócić uwagę na wyrażenia regularne
się tam wyrażenia takie jak „nabożeństwa czerwcowe” czy „nabożeństwa maryjne”.
\section{Anotator danych}
\label{sec:anotator}
\begin{figure}[tbh!]
@ -698,13 +701,21 @@ W algorytmie \ref{alg:has_mass} warto zwrócić uwagę na wyrażenia regularne
\end{figure}
Na rysunku \ref{pic:anotator} został przedstawiony fragment architektury
systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w tym podrozdziale.
systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w niniejszym podrozdziale.
\subsection{Ogólny zarys}
\label{subsec:anotator}
\begin{figure}[tbh!]
\center
\includegraphics[width=0.4\hsize]{antoator.jpg}
\caption{Zrzut ekranu pokazujący interfejs anotatora na urządzeniu mobilnym.}
\label{pic:antoator}
\end{figure}
Anotator danych został stworzony w celu zebrania jak największej ilości
danych dla klasyfikatora przewidującego czy zaznaczony fragment jest godziną
rozpoczęcia mszy świętej, czy nie.
Aby osiągnąć zamierzony cel anotator został zaprojektowany w ten sposób aby:
Żeby osiągnąć zamierzony cel, anotator został zaprojektowany w ten sposób, aby:
\begin{itemize}
\item był szybki,
\item był dostępny na urządzeniach mobilnych i stacjonarnych,
@ -712,60 +723,467 @@ Aby osiągnąć zamierzony cel anotator został zaprojektowany w ten sposób aby
\item umożliwiał wykrywanie oszustów (osób intencjonalnie źle anotujących).
\end{itemize}
\noindent Anotator jest dostępny jako aplikacja internetowa pod adresem \url{msze.nsupdate.info}. Aplikacja jest
responsywna, więc można z niej wygodnie korzystać na każdym urządzeniu
wyposażonym w co najmniej 4 calowy wyświetlacz. Interfejs jest przejrzysty i
został pokazany na rysunku X. Jedyne akcje jakie może wykonać użytkownik to:
wyposażonym w co najmniej 4-calowy wyświetlacz. Interfejs jest przejrzysty i
został pokazany na rysunku \ref{pic:antoator}. Jedyne akcje, jakie może wykonać użytkownik to:
\begin{itemize}
\item kliknąć „Tak” jeśli zaznaczono godzinę rozpoczęcia mszy,
\item kliknąć „Nie” jeśli zaznaczono inną godzinę,
\item kliknąć „Tak”, jeśli zaznaczono godzinę rozpoczęcia mszy,
\item kliknąć „Nie”, jeśli zaznaczono inną godzinę,
\item cofnąć się do poprzedniej anotacji,
\item wyświetlić instrukcję obsługi.
\end{itemize}
Po naciśnięciu przycisku „Tak” lub „Nie” ekran jest automatycznie przewijany na
sam dół. Taka operacja zapewnia łatwy dostęp do przycisków odpowiedzialnych za anotację. Dzięki
temu znajdują się one również zawsze w tym samym miejscu co ułatwia szybką
temu znajdują się one również zawsze w tym samym miejscu, co ułatwia szybką
anotację.
Po naciśnięciu przycisku „Cofnij” ekran nie jest już przewijany na sam dół. W
ten sposób zapewniono wygodny dostęp do przycisku „Cofnij”. Jest to szczególnie
istotne w przypadku gdy
użytkownik zamierza cofać się wiele razy.
Aby zapewnić odpowiednią jakość anotacji przy pierwszym urchomieniu wyświetlana
jest instrukcja obsługi. Opisuje ona sposób w jaki należy anotować godziny oraz
przedstawia przykłady poprawnie zanotowanych godzin. Intrukcję można zamknąć
Aby zapewnić odpowiednią jakość anotacji, przy pierwszym uruchomieniu wyświetlana
jest instrukcja obsługi. Opisuje ona sposób, w jaki należy anotować godziny oraz
przedstawia przykłady poprawnie zaanotowanych godzin. Instrukcję można zamknąć
dopiero po przewinięciu jej na sam dół.
Aplikacja nie wymaga logowania. Taka
decyzja została podjęta ze względu na fakt, że anotatorami są wolontariusze.
Wymóg rejestracji i logowania spowodowałby zmniejszenie liczby osób chętnych do
anotacji. Takie podejście wiąże się jednak z problemem identyfikacji
użytkowników. Identyfikacja jest niezbędna do prawidłowego funkcjonawania
antotora. Chcielibyśmy wiedzieć, które godziny zostały zanotowane przez danego
użytkowników. Identyfikacja jest niezbędna do prawidłowego funkcjonowania
antotora. Chcielibyśmy wiedzieć, które godziny zostały zaanotowane przez danego
użytkownika, aby między innymi nie dać mu tych samych godzin do anotacji.
\subsection{Identyfikacja urządzeń}
Skuteczną identyfikację można przeprowadzić używając
\enlargethispage{3\baselineskip}
Skuteczną identyfikację można przeprowadzić, używając ciasteczek oraz pobierając różne informacje o urządzeniu.
Za pomocą biblioteki \mintinline{text}{fingerprintjs2} można między innymi zebrać następujące
dane o kliencie\cite{fingerprintjs2}:
\begin{enumerate}
\item wersję przeglądarki,
\item język,
\item głębię koloru,
\item rozdzielczość ekranu,
\item strefę czasową,
\item obsługę \textit{localStorage}\footnote{Obiekt przechowujący dane w
przeglądarce bez daty ważności.},
\item obsługę \textit{sessionStorage}\footnote{Obiekt przechowujący dane w
przeglądarce tylko na czas sesji (po zamknięciu przeglądarki dane są usuwane).},
\item wspieranie \textit{indexed DB}\footnote{Niskopoziomy interfejs API dla
transakcyjnej bazy danych do przechowywania ustrukturyzowanych danych.},
\item klasę CPU,
\item system operacyjny,
\item listę zainstalowanych czcionek,
\item listę zainstalowanych wtyczek,
\item \textit{Canvas fingerprint}\footnote{Mechanizm do tworzenia odcisków palca
przeglądarki na podstawie HTML5 Canvas. HTML5 Canvas to element języka HTML
służący do renderowania obrazów bitmapowych.},
\item \textit{WebGL fingerprint}\footnote{Mechanizm do tworzenia odcisków palca
przeglądarki na podstawie obrazków generowanych przez silnik do rysowania
grafiki \textit{WebGL}.},
\item \textit{Audio fingerprint}\footnote{Mechanizm do tworzenia odcisków palca
przeglądarki za pomocą analizy sygnału audio.},
\item \textit{Pixel ratio}\footnote{Jest to stosunek rozdzielczości logicznej do
rozdzielczości fizycznej.},
\item liczbę procesorów logicznych,
\item pojemność pamięci RAM.
\end{enumerate}
\noindent Nadawanie identyfikatora nowemu urządzeniu, a potem jego identyfikacja przedstawia się następująco:
\begin{enumerate}
\item Klient wysyła żądanie GET w celu załadowania anotatora.
\item Anotator ładuje się w przeglądarce i oblicza \textit{odcisk
palca}\footnote{Odcisk palca przeglądarki
to informacje zebrane w celu jej identyfikacji.}
przeglądarki za pomocą biblioteki \textit{fingerprintjs2}. Obliczony \textit{odcisk
palca} będzie dołączany do każdego kolejnego żądania.
\item Klient wysyła serwerowi nowe żądanie z prośbą wyświetlenia fragmentu z
godziną do anotacji. Wraz z żądaniem przesyłany jest \textit{odcisk palca} przeglądarki.
\item Serwer odbiera żądanie od klienta i oblicza unikalny identyfikator dla
klienta. Serwer zapisuje w bazie danych, że \textit{odciskowi palca} wysłanemu przez
klienta odpowiada wygenerowany identyfikator.
\item Serwer wysyła klientowi fragment do anotacji wraz z wcześniej
wygenerowanym identyfikatorem, który zostaje zapisany w nagłówku \textit{Set-Cookie}.
\item Klient odbiera fragment do anotacji. Zostaje on wyświetlony na ekranie
urządzenia. Identyfikator zawarty w nagłówku \textit{Set-Cookie} zostaje
zapisany w przeglądarce klienta. W tym momencie kończy się ładowanie anotatora.
\item Przy każdym kolejnym żądaniu ciasteczko z
identyfikatorem jest wysyłane do serwera. Na jego podstawie serwer
identyfikuje dane urządzenie. Jeśli użytkownik usunie ciasteczka z
urządzenia i wyśle kolejne zapytanie, to serwer zidentyfikuje użytkownika po
\textit{odcisku palca} przeglądarki i w nagłówku \textit{Set-Cookie} prześle
pierwotny identyfikator przydzielony danemu urządzeniu.
\end{enumerate}
\enlargethispage{3\baselineskip}
\subsection{Architektura anotatora}
Architektura
\subsection{Podsumowanie}
Architektura anotatora została przedstawiona na rysunku \ref{pic:anotator_detailed}.
Komunikacja między serwerem a klientem przedstawia się następująco:
\begin{enumerate}
\item Klient wysyła żądanie do serwera.
\item Serwer \textit{nginx} odbiera żądanie od klienta i przekazuje je serwerowi
\textit{Gunicorn}.
\item Serwer \textit{Gunicorn} przekazuje żądanie wolnemu wątkowi roboczemu.
Jeśli każdy wątek roboczy jest zajęty, żądanie zostanie przekazane
pierwszemu wolnemu wątkowi roboczemu.
\item Aplikacja webowa \textit{Flask} przetwarza żądanie. W zależności od żądania odpowiednio
modyfikuje dane w bazie \textit{Redis}.
\item Aplikacja webowa \textit{Flask} zwraca kolejną godzinę do
anotacji z \textit{listy fragmentów do anotacji} i przekazuje ją w postaci
odpowiedzi do serwera \textit{Gunicorn}.
\item Serwer \textit{Gunicorn} odbiera odpowiedź i przekazuje ją serwerowi \textit{nginx}.
\item Serwer \textit{nginx} wysyła odpowiedź klientowi.
\end{enumerate}
\clearpage
\begin{figure}[t]
\centering
\includegraphics[width=0.65\hsize]{annotator_detailed.png}
\caption{Architektura anotatora.}
\label{pic:anotator_detailed}
\end{figure}
\section{Regułowa ekstrakcja godzin mszy}
Do napisania
\section{Klasyfikacja godzin}
Do napisania
\subsection{Model teoretyczny}
\subsection{FastText}
\begin{figure}[tbh!]
\center
\includegraphics[width=0.6\hsize]{ekstraktor_regulowy.png}
\caption{Fragment architektury systemu przedstawiający komponent odpowiedzialny
za ekstrakcję godzin rozpoczęcia mszy świętych.}
\label{pic:ekstraktor_regulowy}
\end{figure}
Na rysunku \ref{pic:ekstraktor_regulowy} został przedstawiony fragment architektury
systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w niniejszym podrozdziale.
Ekstraktor regułowy oparty jest na wyrażeniach regularnych.
Wyróżniamy pięć kluczowych fragmentów wyszukiwanych przez ekstraktor godzin. Są
to:
\begin{description}[labelindent=15pt, style=multiline, leftmargin=5.5cm]
\item [główny nagłówek] -- nagłówek rozpoczynający spis godzin mszy świętych (np. \say{porządek mszy}) lub \say{msze
święte}. Jest on ekstrahowany przez wyrażenie regularne\footnote{Zakładamy
, że wyrażenia regularne ignorują wielkość liter.}\\
\mintinline[breaklines]{text}{'porządek mszy (świętych|św|św\.)|}\\
\mintinline[breaklines]{text}{msz[ea][\n]+([śs]wi[eę]t[ea]|św|św\.)'}
\item [nagłówek niedzielny] -- nagłówek, po którym występują niedzielne i świąteczne
godziny mszy (np. \say{porządek świąteczny}). Jest on ekstrahowany przez
wyrażenie regularne\\
\mintinline[breaklines]{text}{'niedziel[a|e][ \n]+i[ \n]+(dni[ \n]+}\\
\mintinline[breaklines]{text}{(świąteczne|św|św\.)|święta)|niedziel[ea]|}\\
\mintinline[breaklines]{text}{porządek świąteczny'}
\item [niedzielne godziny] -- niedzielne i świąteczne godziny mszy świętych.
Są one ekstrahowane przez wyrażenie regularne \\\mintinline[breaklines]{text}{'.*[^\d]\d{1,2}[^\d].*?''}
\item [nagłówek powszedni] -- nagłówek, po którym występują godziny mszy
świętych dla dni powszednich (np. \say{w tygodniu}). Jest on ekstrahowany
przez wyrażenie regularne \\\mintinline[breaklines]{text}{'dzień powszedni|dni powszednie|w tygodniu| porządek zwykły|od poniedziałku do soboty'}
\item [powszednie godziny] -- powszednie godziny mszy świętych. Są one
ekstrahowane przez wyrażenie regularne \\\mintinline[breaklines]{text}{'(.*?[^\d\n]?\d{1,2}[^\d\n]?.*?\n)+'}.
\end{description}
W dużym uproszczeniu ekstrakcja godzin przedstawia się następująco:
\begin{enumerate}
\item Wyszukaj \textit{nagłówek główny}, \textit{nagłówek niedzielny} i
\textit{nagłówek powszedni} w taki sposób, aby:
\begin{itemize}
\item \textit{nagłówek niedzielny} był za \textit{nagłówkiem głównym}, ale
przed \textit{nagłówkiem powszednim}.
\item między \textit{nagłówkiem głównym} a \textit{nagłówkiem powszednim}
nie znajdował się żaden inny \textit{nagłówek} niż
\textit{nagłówek niedzielny}
\end{itemize}
\item Jeśli wyszukiwanie w kroku 2. się nie powiodło, szukaj na kolejnej stronie parafialnej.
\item Niedzielnymi i świątecznymi godzinami mszy świętych będą godziny między
\textit{nagłówkiem niedzielnym} a \textit{nagłówkiem powszednim} pasujące
do wyrażenia regularnego \textit{niedzielnych godzin}. Jeśli wyszukiwanie
się nie powiedzie, to rozpocznij szukanie od początku na kolejnej stronie parafialnej.
\item Godzinami powszednimi, będą godziny po \textit{nagłówku powszednim}
pasujące do wyrażenia regularnego \textit{powszednich godzin}. Jeśli wyszukiwanie
się nie powiedzie, to rozpocznij szukanie od początku na kolejnej stronie parafialnej.
\end{enumerate}
\section{Klasyfikacja godzin}
\label{sub:klasyfikacja}
\begin{figure}[tbh!]
\center
\includegraphics[width=0.9\hsize]{klasyfikator.png}
\caption{Fragment architektury systemu przedstawiający komponent odpowiedzialny
za klasyfikację godzin.}
\label{pic:klasyfikator}
\end{figure}
Na rysunku \ref{pic:klasyfikator} został przedstawiony fragment architektury
systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w niniejszym podrozdziale.
Klasyfikator opary jest na płytkich sieciach neuronowych optymalizowanych metodą
stochastycznego spadku wzdłuż gradientu z
liniowo malejącym współczynnikiem uczenia. Został on wykorzystany do klasyfikacji
godzin na te będące godzinami mszy świętych i na te nimi niebędące.
\subsection{Model teoretyczny}
\label{subsec:model_teoretyczny}
Podrozdział opiera się na artykule \textit{word2vec Parameter Learning
Explained}\cite{word2vec} i artykule \textit{Bag of Tricks for Efficient Text Classification}\cite{fasttext}.
\subsubsection{Notacja}
W podrozdziale \ref{subsec:model_teoretyczny} przyjęto poniższą notację.
\boldmath %\unboldmath
\begin{description}[labelindent=25pt, style=multiline, leftmargin=2.5cm]
\item[$X_{V\times N}$] -- macierz $X$ o $V$ wierszach i $N$ kolumnach.
\item [$X_{i,j}$] -- wartość w macierzy $X$ w wierszu $i$ i kolumnie $j$.
\item [$X_{i,*}$] -- wiersz $i$ w macierzy $X$.
\item [$X_{*,j}$] -- kolumna $j$ w macierzy $X$.
\item [$x_i$] -- $x_i$ wartość pod indeksem $i$ w wektorze $x$.
\item [$w_i$] -- wektor słowa o indeksie $i$.
\item [$w_{i,j}$] -- wartość pod indeksem $j$ w $i$-tym słowie.
\end{description}
\subsubsection{Architektura sieci}
\begin{figure}[tbh!]
\center
\includegraphics[width=0.6\hsize]{cbow.png}
\caption{Architektura sieci neuronowej.}
\label{pic:cbow}
\end{figure}
Rysunek \ref{pic:cbow}\footnote{Rysunek wzorowany jest na rysunku z artykułu \textit{word2vec Parameter Learning
Explained}\cite{word2vec}} przedstawia sieć neuronową, która służy do klasyfikacji
tekstu.
Wejście do sieci składa się z wektorów słów $w_1, \dots, w_C$, gdzie $w_1,
\dots, w_C$ to słowa z klasyfikowanego zdania. Wektory słów zakodowane
zostały za pomocą kodowania \textit{one-hot encoding}\footnote{Sposób kodowania
zwany jako \say{kod 1 z n}.}.
Na wejściu mamy $C$ wektorów słów o rozmiarze $V$, gdzie $V$ to rozmiar
słownika, a $C$ to liczba słów w zdaniu. Każdy wektor słów połączony jest z warstwą
ukrytą $h$ macierzą wag $W_{V\times N}$ (współdzielą tę samą macierz). Warstwa
ukryta $h$ jest rozmiaru $N$. Warstwa ukryta $h$ łączy się z warstwą wyjściową
macierzy $H_{N\times K}$. Warstwa wyjściowa $y$ jest rozmiaru $K$, gdzie $K$
to liczba klas.
Sieć klasyfikuje zdania do klas $k_1, \dots, k_K$.
\subsubsection{Propagacja w przód}
Warstwa ukryta jest wynikiem średniej z wektorów słów $w_1, \dots,
w_C$\footnote{Zakładamy, że wektory są wektorami wierszowymi.}
pomnożonych przez macierz $W_{V\times N}$ (patrz równanie \ref{eq:hidden}).
\begin{equation}
\label{eq:hidden}
h=\frac{1}{c} \sum_{i=1}^{C}{w_i W}=\frac{1}{c} (\sum_{i}^{C}{w_i }) \cdot W
\end{equation}
W warstwie wyjściowej jako funkcja aktywacji została zastosowana funkcja
\textit{softmax}\cite{softmax}. Wejście o indeksie $j$ do funkcji \textit{softmax} obliczane jest za pomocą równania \ref{eq:softmax_input}.
\begin{equation}
\label{eq:softmax_input}
u_j=h\cdot H_{*,j}
\end{equation}
$y_j$ w warstwie wyjściowej otrzymujemy używając funkcji \textit{softmax} zgodnie z równaniem \ref{eq:output_y}
\begin{equation}
\label{eq:output_y}
y_j = \frac{exp(u_j)}{\sum_{i=1}^{K}{exp(u_i)}}
\end{equation}
Funkcja \textit{softmax} normalizuje nam wektor wyjściowy. Dzięki niej na
wyjściu z sieci otrzymujemy rozkład prawdopobieństwa klas. Możemy zatem zapisać, że
\begin{equation}
\label{eq:probyj}
p(k_j|w_1,w_2, \dots, w_C) = y_j,
\end{equation}
gdzie $k_j$ to klasa o indeksie $j$.
\subsubsection{Proces uczenia sieci neuronowej}
Proces uczenia zaczynamy od zainicjalizowania macierzy $W_{V\times N}$ i
$H_{N\times K}$ losowymi wartościami. Następnie przeprowadzamy propagację w
przód i obliczamy błąd między aktualnym a oczekiwanym wyjściem. Następnie
obliczamy gradient funkcji kosztu i poprawiamy wartości macierzy $W$ i $H$ w
kierunku gradientu.
Celem jest maksymalizacja prawdopobieństwa $p(k_{j^*}|w_1, \dots w_C)$ (patrz równania \ref{eq:max_start} - \ref{eq:max_end}), gdzie $k_{j^*}$
to wyjściowa klasa o indeksie $j^*$.
\begin{align}
\label{eq:max_start}
max(p(k_{j^*}|w_1, \dots w_C)) &= max(\frac{exp(u_{j^*})}{\sum_{i=1}^{K}{exp(u_i)}}) &\text{z \ref{eq:probyj} i \ref{eq:output_y}}\\
&= max(log(\frac{exp(u_{j^*})}{\sum_{i=1}^{K}{exp(u_i)}}))\\
\label{eq:max_end}
&= max(u_{j^*} - log(\sum_{i=1}^{K}{exp(u_i)}))
\end{align}
Zatem funkcja kosztu (celem jest jej minimalizacja) będzie przedstawiała się tak
jak na równaniu \ref{eq:loss}.
\begin{align}
E&=-(u_{j^*} - log(\sum_{i=1}^{K}{exp(u_i)})) &\text{z \ref{eq:max_end}}\\
\label{eq:loss}
&=log(\sum_{i=1}^{K}{exp(u_i)}) -u_{j^*}
\end{align}
\subsubsection{Aktualizowanie wag macierzy $H_{N\times K}$}
Najpierw należy policzyć pochodną cząstkową funkcji kosztu $E$ względem wektora
$u$ (patrz równania \ref{eq:deu_start} - \ref{eq:deu_end}).
\begin{align}
\label{eq:deu_start}
\frac{\partial E}{\partial u_j} &= \frac{\partial(log(\sum_{i=1}^{K}{exp(u_i)}) -u_{j^*})}{\partial u_j}\\
&=\frac{\partial(log(\sum_{i=1}^{K}{exp(u_i)}))}{\partial u_j} - \frac{\partial u_{j^*}}{\partial u_{j}}\\
\shortintertext{Z reguły łańcuchowej otrzymujemy:}
&=\frac{\partial(\sum_{i=1}^{K}{exp(u_i)})}{\partial u_{j}} \cdot \frac{\partial(log(\sum_{i=1}^{K}{exp(u_i)}))}{\partial(\sum_{i=1}^{K}{exp(u_i)})} - \frac{\partial u_{j^*}}{\partial u_{j}}\\
&= exp(u_j) \cdot \frac{1}{\sum_{i=1}^{K}{exp(u_i)}} - \frac{\partial u_{j^*}}{\partial u_{j}}\\
&= y_j - \frac{\partial u_{j^*}}{\partial u_{j}} &\text{z \ref{eq:output_y}}\\ \shortintertext{Za $\frac{\partial u_{j^*}}{\partial u_{j}}$ podstawiamy $t_j$:}
\label{eq:deu_end}
&= y_j - t_j \vcentcolon= e_j\\\shortintertext{gdzie $t_j = 1$, gdy $j = j^*$, w przeciwnym wypadku $t_j = 0$.}\nonumber
\end{align}
Pochodna $e_j$ to błąd predykcji warstwy wyjściowej.
Gradient dla wag z macierzy $H$ otrzymamy, licząc pochodną cząstkową
funkcji kosztu $E$ względem wag macierzy $H$ (patrz równania \ref{eq:der_start} - \ref{eq:der_end}).
\begin{align}
\label{eq:der_start}
\frac{\partial E}{\partial H_{i,j}}&=\frac{\partial E}{\partial u_j} \cdot \frac{\partial u_j}{\partial H_{i,j}} &\text{z reguły łańcuchowej}\\
&= e_j \cdot \frac{\partial(h \cdot H_{*,j})}{\partial H_{i,j}} &\text{z \ref{eq:softmax_input}}\\
&= e_j \cdot \frac{\partial(\sum_{i'=1}^{N}{h_{i'} \cdot H_{i',j}})}{\partial H_{i,j}} &\text{z definicji mnożenia macierzy}\\
\label{eq:der_end}
&= e_j \cdot h_i
\end{align}
\noindent Aktualizowanie wag macierzy $H$ zostało przedstawione w równaniu \ref{eq:update_h}.
\begin{align}
\label{eq:update_h}
H_{i,j}^{nowe} = H_{i,j}^{stare} - \eta \cdot e_j \cdot h_i\\ \shortintertext{gdzie $\eta$ to liniowo malejący współczynnik uczenia.}\nonumber
\end{align}
\subsubsection{Aktualizowanie wag macierzy $W_{V\times N}$}
Najpierw należy policzyć pochodną cząstkową funkcji kosztu $E$ względem warstwy
ukrytej $h$ (patrz równania \ref{eq:sumder_start} - \ref{eq:sumder_end}).
\begin{align}
\label{eq:sumder_start}
\frac{\partial E}{\partial h_i} &= \sum_{j=1}^{K}{\frac{\partial E}{\partial u_j} \cdot \frac{\partial u_j}{\partial h_i}} &\text{z reguły łańcuchowej}\\
&= \sum_{j=1}^{K}{e_j \cdot \frac{\partial(h \cdot H_{*,j})}{\partial h_i}} &\text{z \ref{eq:softmax_input} i z \ref{eq:deu_start} - \ref{eq:deu_end}}\\
&= \sum_{j=1}^{K}{e_j \cdot \frac{\partial(\sum_{i'=1}^{N}{h_i' \cdot H_{i',j}})}{\partial h_i}} &\text{z definicji mnożenia macierzy}\\
\label{eq:sumder_end}
&= \sum_{j=1}^{K}{e_j \cdot H_{i,j}}
\end{align}
W równaniu \ref{eq:sumder_start} mamy do czynienia z sumą ze względu na fakt,
że neuron $h_i$ połączony jest z $K$ neuronami warstwy wyjściowej. Każdy błąd
predykcji powinien być uwzględniony.
Następnie należy policzyć pochodną cząstkową funkcji $E$ względem wag w macierzy
$W$ (patrz \ref{eq:last_der_start} - \ref{eq:last_der_end}).
\begin{align}
\label{eq:last_der_start}
\shortintertext{Z reguły łańcuchowej:}
\frac{\partial E}{\partial W_{k,i}} &= \frac{\partial E}{\partial h_i} \cdot \frac{\partial h_i}{\partial W_{k,i}}&\text{}\\
\shortintertext{Z \ref{eq:sumder_start} - \ref{eq:sumder_end} i z \ref{eq:hidden}:}
&= (\sum_{j=1}^{K}{e_j \cdot H_{i,j}}) \cdot \frac{\partial (\frac{1}{C}(\sum_{i'=1}^{C}{w_{i'}})W_{*,i})}{\partial W_{k,i}}\\
\shortintertext{Z definicji mnożenia macierzy:}
&=(\sum_{j=1}^{K}{e_j \cdot H_{i,j}}) \cdot \frac{\partial (\frac{1}{C}\sum_{l=1}^{V}((\sum_{i'=1}^{C}{w_{i',l}})W_{l,i}))}{\partial W_{k,i}}\\
&=(\sum_{j=1}^{K}{e_j \cdot H_{i,j}}) \cdot \frac{1}{C}\sum_{i'=1}^{C}{w_{i',k}}\\
\intertext{Zauważmy, że $\sum_{i'=1}^{C}{w_{i',k}}=1$, bo wektory słów zakodowane są kodowaniem \textit{one-hot encoding}. Innymi słowy jest tylko jeden wektor słowa, który ma wartość 1 pod indeksem $k$. Reszta wektorów słów ma pod indeksem $k$ wartość 0. Zatem otrzymujemy:}
&=\frac{1}{C}\sum_{j=1}^{K}{e_j \cdot H_{i,j}}
\label{eq:last_der_end}
\end{align}
\noindent Aktualizowanie wag macierzy $W$ zostało przedstawione w równaniu \ref{eq:final}.
\begin{equation}
\label{eq:final}
W_{i,j}^{nowe} = W_{i,j}^{stare} - \eta \frac{1}{C} \sum_{j=1}^{K}{e_j \cdot H_{i,j}}
\end{equation}
\subsection{FastText}
Autorzy biblioteki \textit{fastText} wskazują, że podstawowy model opisany w
podrozdziale \ref{subsec:model_teoretyczny} można usprawnić. Do modelu można
dodać dodatkowe cechy w postaci \textit{n-gramów}(w modelu z podrozdziału
\ref{subsec:model_teoretyczny} zostały zastosowane unigramy). Artykuł
\textit{Bag of Tricks for Efficient Text Classification}\cite{fasttext} pokazuje,
że dodanie bigramów poprawia wyniki klasyfikatora.
Ponadto, aby przyspieszyć trenowanie, można zastosować funkcję \textit{hierarchical
softmax}\cite{fasttext}, zamiast funkcji \textit{softmax}. Taka operacja jest korzystna w
przypadku dużej liczby klas \cite{fasttext}. W przypadku klasyfikacji godzin użyto funkcji
\textit{softmax} ze względu na małą liczbę klas.
Do klasyfikacji użyto biblioteki \textit{fastText} z domyślnymi parametrami.
Rezultaty zostały przedstawione w rozdziale \ref{ch:rezultaty}.
\chapter{Rezultaty}
Do napisania
% \section{Organizacja danych} % może zbyt inżynierskieby
\label{ch:rezultaty}
W niniejszym rozdziale zebrane zostały wyniki, jakie osiągnął system ekstrakcji
informacji o godzinach rozpoczęcia mszy świętych.
\subsubsection{Dane parafii i ich adresy URL}
\noindent Udało się zebrać:
\begin{itemize}
\item \textbf{10130} nazw i adresów parafii,
\item \textbf{5600} adresów internetowych stron parafialnych,
\end{itemize}
Ręcznie na małej próbce adresów
URL stwierdzono, że
w ponad 90\% prowadzą one do poprawnych parafii.
Warto zaznaczyć, że w momencie oddania pracy do druku nie znaleziono
obszerniejszego zbioru adresów URL parafii. Serwisy internetowe zawierające
adresy URL parafii posiadały nie więcej niż 2500 tysiąca adresów URL parafii.
Większość z nich to były błędne adresy internetowe.
\subsubsection{Pająk}
Z \textbf{5600} adresów internetowych parafii pająk zaindeksował \textbf{5177} stron parafialnych.
W kilka dni pobrał około \textbf{3 000 000} stron HTML o łącznym rozmiarze \textbf{152G}. Po
konwersji stron parafialnych z formatu HTML do formatu tekstowego otrzymano \textbf{22G} tekstu.
\subsubsection{Anotator}
W dwa tygodnie od udostępnienia anotatora udało się:
\begin{itemize}
\item zebrać \textbf{10260} anotacji godzin,
\item zaanotować \textbf{9313}\footnote{Dopuszczane jest by jedna godzina była
anotowana przez wielu unikalnych użytkowników. Stąd rozbieżność między
liczbą anotacji a zaanotowanymi godzinami.} z \textbf{10920} godzin.
\end{itemize}
Dane anotowano z \textbf{177} unikalnych urządzeń.
Średni czas anotacji na urządzenie wyniósł \textbf{2,5} sekundy.
Liczba urządzeń, z których anotowano godziny mszy świętych świadczy o
zainteresowaniu społeczności katolickiej projektem automatycznego ekstraktora
godzin mszy świętych. Entuzjazm udzielał się również w komentarzach na
Facebook'u (komentarze pod postem z prośbą o anotowanie godzin mszy świętych).
Średni czas anotacji, jak i liczba zaangażowanych użytkowników potwierdzają cechy anotatora
wymienione
w podrozdziale \ref{subsec:anotator} (szybkość, dostępność i wygoda użytkowania).
\subsubsection{Regułowy ekstraktor danych}
Regułowy ekstraktor danych był w stanie znaleźć godziny mszy świętych dla około
\textbf{2600} parafii z \textbf{5177} parafii. Na małej próbce parafii ręcznie stwierdzono bardzo wysoką precyzję
ekstrahowanych danych.
\subsubsection{Klasyfikator godzin}
Do ewaluacji ekstraktora godzin wykorzystano dane zebrane przez anotator. Z 9313 zaanotowanych
godzin 80\% użyto do trenowania klasyfikatora, a 20\% do ewaluacji. Nie
przeprowadzono optymalizacji parametrów.
\noindent Otrzymano następujące wyniki:
\begin{itemize}
\item \makebox[3.8cm][l]{wartość pokrycia} $= 0,884$
\item \makebox[3.8cm][l]{precyzja} $= 0,850$
\item \makebox[3.8cm][l]{F1\footnote{F1 to średnia harmoniczna z wartości pokrycia i precyzji.}} $= 0,884$
\item \makebox[3.8cm][l]{dokładność} $= 0,858$
\end{itemize}
Wyniki są obiecujące i z pewnością można je w przyszłości znacznie poprawić.
%\textbf{9313} anotacji godzin w \textbf{dwa tygodnie} od udostępnienia anotatora,
\chapter{Podsumowanie}
Do napisania
W pracy opisany został zrobiony przeze mnie system do ekstrakcji informacji
godzin rozpoczęcia mszy świętych. Na początku przedstawiłem komponent
odpowiedzialny za zbieranie informacji o parafiach. Następnie przybliżyłem
metodę wyszukiwania adresów internetowych parafii. Potem dokładnie omówiłem
architekturę pająka do pobierania stron parafialnych.
W kolejnych rozdziałach krótko opisałem bibliotekę do konwersji tekstu,
ekstraktor godzin oraz wyszukiwanie stron, na których z dużym prawdopodobieństwem
znajdują się godziny mszy. Następnie omówiłem anotator służący do zbierania
danych do uczenia maszynowego. Anotator dostępny jest pod adresem
\url{msze.nsupdate.info}. Potem krótko opowiedziałem o regułowym ekstraktorze
danych. W kolejnym rozdziale przedstawiłem model teoretyczny klasyfikatora
godzin mszy. W szczególności wyprowadziłem równania na aktualizacje wag sieci
neuronowej.
Na końcu przedstawiłem informacje o wszystkich zebranych danych oraz wynikach
anotatora, ekstraktora godzin mszy świętych i klasyfikatora godzin. Otrzymane
rezultaty świadczą o sensowności projektu i zachęcają do jego dalszego rozwoju.
% \subsection{Ewaluacja wewnętrzna} %F1 score
% \subsection{Ewaluacja zewnętrzna} % w systemie webowym, użytkownicy

View File

@ -1,4 +1,10 @@
\chapter*{Streszczenie}
TODO
Praca przedstawia proces tworzenia systemu ekstrakcji informacji o godzinach
rozpoczęcia mszy świętych. Opisane zostają sposoby zbierania danych o polskich
parafiach, w szczególności proces tworzenia pająków. Następnie pokazane zostają
dwie metody ekstrakcji godzin rozpoczęcia mszy świętych: regułowa i oparta na
uczeniu maszynowym. Większa uwaga zostaje poświęcona metodzie opartej na uczeniu
maszynowym, która polega na wykorzystaniu klasyfikatora tekstu.
\textbf{Słowa kluczowe:} ekstrakcja informacji
\textbf{Słowa kluczowe:} ekstrakcja informacji, indeksowanie stron
internetowych, klasyfikacja tekstu

View File

@ -1,2 +1,35 @@
\markboth{Wstęp}{Wstęp}
\addcontentsline{toc}{chapter}{Wstęp}
\chapter*{Wstęp}
Msza święta to najważniejsze duchowe wydarzenie w tygodniu chrześcijanina. Każdy wierzący katolik uczęszcza na niedzielną mszę świętą, a wielu również na msze święte w dni powszednie.
Ze względu na rangę tego wydarzenia powstało kilka serwisów, które umożliwiają
wyszukiwanie najbliższej godziny i miejsca mszy świętej. Z jednej strony
powstały wyszukiwarki ogólnopolskie takie jak \url{kiedymsza.pl} lub
\url{msze.info}. Wadą tych wyszukiwarek jest to, że wyświetlane godziny mszy
świętych bardzo często są albo błędne, albo już nieaktualne.
Z tego względu nie zdobyły one dużej popularności.
Z drugiej strony powstały wyszukiwarki lokalne jak na
przykład wyszukiwarka mszy świętych dla archidiecezji łódzkiej
\url{archidiecezja.lodz.pl/wyszukiwarka-mszy-swietych/} lub aplikacja mobilna Drogowskaz\footnote{\url{www.aplikacjadrogowskaz.pl}}
służąca do wyszukiwania mszy świętych w archidiecezji poznańskiej. Oczywistą
wadą tych wyszukiwarek jest to, że obejmują małą liczbę polskich parafii.
Oferują one za to bardzo wiarygodne informacje i są częściej aktualizowane.
Zarówno
ogólnopolskie, jak i lokalne wyszukiwarki mszy świętych zbierają swoje dane
manualnie. Dane wpisują albo internauci, albo autorzy wyszukiwarek. W celu
zasięgnięcia informacji dzwonią oni do parafii lub przepisują godziny mszy
świętych ze stron parafialnych. Takie postępowanie jest bardzo czasochłonne i kosztowne.
Niniejsza praca przedstawia system, który służy do automatycznego zbierania
informacji o godzinach rozpoczęcia mszy świętych. W pierwszym rozdziale dokładnie opisano system
ekstrakcji godzin mszy świętych. W drugim rozdziale przedstawiono osiągnięte
rezultaty. W trzecim rozdziale podsumowano pracę.
W momencie oddania pracy do druku system opisany w niniejszej pracy jest jedynym
w Polsce automatycznym system ekstrakcji godzin mszy świętych.
System przykuł uwagę jednego z
autorów Drogowskazu. Zostały przeprowadzone wstępne rozmowy i jeśli system się
sprawdzi, to być może będzie dostarczał dane dla aplikacji Drogwskaz.
%%% Local Variables:
%%% LaTeX-command: "latex -shell-escape"
%%% End: