tmp2
@ -60,6 +60,7 @@ Fourteenth International Conference on Computational Linguistics, Nantes, France
|
||||
@misc{binaryornot}
|
||||
@misc{html2text}
|
||||
@misc{markdown}
|
||||
@misc{scrapy}
|
||||
@article{parallel,
|
||||
title = {GNU Parallel - The Command-Line Power Tool},
|
||||
author = {O. Tange},
|
||||
|
@ -1 +1 @@
|
||||
<mxfile userAgent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36" version="8.6.5" 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">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</diagram></mxfile>
|
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 160 KiB |
BIN
img/crawler.png
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 16 KiB |
@ -1,5 +1,7 @@
|
||||
\usepackage[OT4]{polski} % tryb pelnej polonizacji
|
||||
\usepackage[utf8]{inputenc} % kodowanie
|
||||
\usepackage{lmodern} %latin modern fonts
|
||||
\usepackage[T1]{fontenc} % ulepszona wersja czcionek dla polski, OT4 jest stare
|
||||
\usepackage{polski}
|
||||
\usepackage{makeidx} % indeks
|
||||
\usepackage[pdftex]{graphicx} % zalaczanie grafiki
|
||||
\usepackage{tikz} % grafika wektorowa
|
||||
@ -23,6 +25,7 @@
|
||||
\usepackage{url} % url w bibliografii
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amsthm}
|
||||
\usepackage[section]{placeins} %wymusza by obrazek był w obrębie sekacji a nie poza nią
|
||||
|
||||
\usepackage{tabularx} %lepsze tabele nie uzywane
|
||||
\usepackage{makecell} % do formatowania cell w tabelach
|
||||
|
716
rozdzial_3.tex
@ -1,72 +1,84 @@
|
||||
\chapter{Podstawy teoretyczne}
|
||||
\chapter{Podstawy teoretyczne/spis pojęć}
|
||||
\chapter{Ekstrakcja godzin rozpoczęcia mszy świętych}
|
||||
\section{Ogólny zarys systemu}
|
||||
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 odpytuje api Google'a w
|
||||
celu znalezienia adresów internetowych parafii.
|
||||
Dla każdej parafii, dla której udało się znaleźć adres url, pobierane są wszystkie
|
||||
podstrony w odległości (sieć to graf) conajwyżej 3 od strony startowej.
|
||||
Architektura systemu ekstrakcji godzin rozpoczęcia mszy świętych została
|
||||
przedstawiona na rysunku \ref{pic:architektura}. W tym podrozdziale zostanie ona
|
||||
krótko opisana. Szczegółowy opis poszczególnych komponentów znajduje się w
|
||||
kolejnych podrozdziałach.
|
||||
|
||||
Z dużej liczby stron parafialnych, za pomocą prostych reguł wyodrębnione zostają
|
||||
te, na których z dużym prawdopodbieństwem znajdują się godziny mszy świętych.
|
||||
Ciągi znaków przypominające godziny mszy świętych zostają wydobyte ekstraktorem
|
||||
o bardzo niskiej precyzji i bardzo wysokim \textit{recall}.
|
||||
Każda godzina wraz z kontekstem w jakim się znajduje trafia do systemu
|
||||
crowdsourcingowego, gdzie jest annotowana jako poprawna lub niepoprawna godzina mszy świętej.
|
||||
Do zannotowanych danych zostają dołączone poprawne godziny mszy świętych
|
||||
znalezione przez
|
||||
regułowy ekstraktor mszy świętych o bardzo wysokiej precyzji. Dodatkowo w celu wyrównania
|
||||
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
|
||||
Google w
|
||||
celu znalezienia adresów internetowych parafii.
|
||||
Dla każdej parafii, dla której udało się znaleźć adres URL, pobierane są wszystkie
|
||||
podstrony w odległości\footnote{Zakładamy, że sieć jest grafem, zatem odległość
|
||||
definiujemy tak jak w teorii grafów.} co najwyżej 3 od strony startowej.
|
||||
|
||||
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
|
||||
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
|
||||
świętej\footnote{\label{hour_note}Przez „niepoprawne
|
||||
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
|
||||
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.
|
||||
|
||||
Finalny ekstraktor godzin mszy świętych utworzony zostaje z połączenia
|
||||
ekstraktora regułowego z ekstraktorem opartym na uczeniu maszynowym.
|
||||
% \bigskip
|
||||
Klasyfikator używany jest do klasyfikacji godzin
|
||||
znalezionych przez ekstraktor godzin do następujących klas:
|
||||
\begin{itemize}
|
||||
\item poprawne godziny mszy świętych,
|
||||
\item niepoprawne godziny mszy świętych.
|
||||
\end{itemize}
|
||||
|
||||
\begin{figure}[tbh!]
|
||||
\noindent Docelowe godziny rozpoczęcia mszy świętych otrzymujemy z:
|
||||
\begin{itemize}
|
||||
\item ekstraktora godzin mszy świętych,
|
||||
\item klasyfikatora godzin.
|
||||
\end{itemize}
|
||||
|
||||
\begin{figure}[!htb]
|
||||
\center
|
||||
\includegraphics[width=1\hsize]{struktura_wyszukiwarki.png}
|
||||
\caption{Architektura ekstraktora godzin mszy świętych.}
|
||||
\label{struktura_pic}
|
||||
\includegraphics[width=1\hsize]{struktura_programu.png}
|
||||
\caption{Architektura systemu do ekstrakcji godzin mszy świętych.}
|
||||
\label{pic:architektura}
|
||||
\end{figure}
|
||||
|
||||
\clearpage
|
||||
|
||||
\newpage
|
||||
\section{Zbieranie informacji o parafiach}
|
||||
\begin{figure}[tbh!]
|
||||
|
||||
\begin{figure}[htb]
|
||||
\center
|
||||
\includegraphics[width=0.7\hsize]{crawler_adresow_trans.png}
|
||||
\label{crawler_adresow_pic}
|
||||
\caption{Fragment architektury systemu przedstawiający komponent odpowiedzialny za zbieranie informacji o parafiach.}
|
||||
\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.
|
||||
|
||||
Dane zostały zebrane z serwisu internetowego deon.pl, który zawiera 10130 parafii.
|
||||
Warto zauważyć, że deon.pl posiada większość polskich parafii, ponieważ według
|
||||
Jest to większość polskich parafii, ponieważ według
|
||||
danych statystycznych GUS\cite{gus} z 2016 roku w Polsce było
|
||||
10255 parafii.
|
||||
|
||||
Dla każdej parafii zebrano:
|
||||
\begin{itemize}
|
||||
\item nazwę parafii,
|
||||
\item miejscowość w której się znajduje,
|
||||
\item województwo w którym się znajduje,
|
||||
\item miejscowość, w której się znajduje,
|
||||
\item dokładny adres,
|
||||
\item nazwę dekanatu do którego należy,
|
||||
\item nazwę diecezji do której przynależy.
|
||||
\item nazwę dekanatu, do którego należy,
|
||||
\item nazwę diecezji, do której przynależy,
|
||||
\item województwo, w którym się znajduje.
|
||||
\end{itemize}
|
||||
Do wydobycia danych użyto skryptu w pythonie, który korzystał z parsera
|
||||
html z biblioteki \textit{BeautifulSoup}\cite{beautiful_soup}. Przy wysyłaniu zapytań do serwisu deon.pl zastosowano
|
||||
algorytm \textit{Expotential Backoff}\cite{expotential_backoff}, który prezentuje się następująco:
|
||||
\begin{enumerate}
|
||||
\item Wyślij zapytanie do serwisu;
|
||||
\item Jeśli zapytanie się powiodło wróć do punktu nr 1, jeśli nie poczekaj 1.5s i wyślij kolejne zapytanie;
|
||||
\item Jeśli zapytanie znów się nie powiodło odczekaj 2.25s i wyślij kolejne
|
||||
zapytanie
|
||||
\item W ogólności czekaj $1.5^t$ sekund zanim wyślesz kolejne zapytanie, gdzie
|
||||
$t$ to liczba następujących po sobie nieudanych zapytań.
|
||||
\end{enumerate}
|
||||
Powyższy algorytm uodparnia skrypt na przejściowe problemy z połączeniem i
|
||||
zapobiega zbyt częstemu odpytywaniu serwisu kiedy ten nie daje sobie rady ze
|
||||
zbyt dużą liczbą zapytań.
|
||||
|
||||
\noindent Fragment zebranych danych został przedstawiony w tabeli \ref{dane_tab}.
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
@ -80,163 +92,235 @@ Dla każdej parafii zebrano:
|
||||
\\ [-1.5ex]
|
||||
\end{tabular}
|
||||
\caption{Fragment zebranych danych.}
|
||||
\label{dane_tab}
|
||||
\end{table}
|
||||
|
||||
\section{Wyszukiwanie stron internetowych parafii}
|
||||
Do wydobycia danych użyto skryptu w języku Python, który korzystał z parsera
|
||||
HTML z biblioteki \textit{BeautifulSoup}\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:
|
||||
|
||||
\begin{algorithm}
|
||||
\setstretch{1.2}
|
||||
\SetAlgorithmName{Algorytm}{algorithm}{List of Algorithms}
|
||||
\caption{\textit{Expotential Backoff}}
|
||||
\label{alg:backoff}
|
||||
\SetAlgoLined
|
||||
\SetKwFunction{Request}{send\_request}
|
||||
\SetKwData{MaxWait}{max\_wait\_time}
|
||||
\SetKwData{MaxRepeat}{repeat\_limit}
|
||||
\SetKwInput{kwInput}{Stałe}
|
||||
\SetKwInput{kwAlg}{Algorytm}
|
||||
\SetKwInput{kwWhere}{gdzie}
|
||||
\kwInput{\\
|
||||
\Indp{\makebox[2.8cm][l]{\MaxWait }} $-$ maksymalny czas oczekiwania.\\
|
||||
{\makebox[2.8cm][l]{\MaxRepeat }} $-$ limit liczby powtórnych zapytań pod rząd.
|
||||
}
|
||||
\bigskip
|
||||
\kwAlg{
|
||||
\begin{enumerate}[rightmargin=5mm]
|
||||
\item Wyślij zapytanie do serwisu;
|
||||
\item Jeśli zapytanie się nie powiodło, poczekaj 2s i wyślij kolejne zapytanie,
|
||||
\item Jeśli zapytanie się nie powiodło, poczekaj 4s i wyślij kolejne zapytanie,
|
||||
\item Jeśli zapytanie się nie powiodło, poczekaj 8s i wyślij kolejne zapytanie,
|
||||
\item Powtarzaj do czasu aż zapytanie się powiedzie lub liczba ponownych
|
||||
zapytań pod rząd wyniesie \MaxRepeat.
|
||||
\end{enumerate}
|
||||
}
|
||||
\kwWhere{
|
||||
\begin{itemize}
|
||||
\setlength\itemsep{0.3em}
|
||||
\item Czas oczekiwania to $2^t$, gdzie $t$ to liczba nieudanych zapytań.
|
||||
\item Czas oczekiwania nie może być większy niż \MaxWait.
|
||||
\end{itemize}
|
||||
}
|
||||
\end{algorithm}
|
||||
|
||||
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ń.
|
||||
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.
|
||||
|
||||
\section{Wyszukiwanie adresów URL parafii}
|
||||
\begin{figure}[tbh!]
|
||||
\center
|
||||
\includegraphics[width=0.7\hsize]{crawler_url_trans.png}
|
||||
\label{crawler_url_pic}
|
||||
\caption{Fragment architektury systemu przedstawiający komponent odpowiedzialny
|
||||
za wyszukiwanie adresów URL parafii.}
|
||||
\label{pic:pajak_url}
|
||||
\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.
|
||||
|
||||
\subsubsection{Pierwsze próby}
|
||||
Do wyszukiwania adresów url parafii próbowano wykorzystać wyszukiwarki takie jak
|
||||
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 robots.txt Google zabrania
|
||||
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 robots.txt Google zabrania
|
||||
korzystania z pająków na ich wyszukiwarce.
|
||||
DuckDuckGo nie blokowało adresu ip, ale zabraniało crawlowania w robots.txt i słabo radziło sobie z polskimi
|
||||
Wyszukiwarka DuckDuckGo nie blokowała adresu IP, ale zabraniała indeksowania w pliku robots.txt i słaba radziła sobie z polskimi
|
||||
zapytaniami. W obu przypadkach powyższa metoda stwarzała kolejny problem do
|
||||
rozwiązania -- z wielu wyników wyszukiwania trzeba było wybrać ten, który zawierał
|
||||
adres url parafii.
|
||||
adres URL parafii.
|
||||
\subsubsection{Rozwiązanie}
|
||||
Po wieleokrotnych 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
|
||||
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
|
||||
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.
|
||||
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
|
||||
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'owi do
|
||||
identyfikacji osoby. Żadna opłata nie jest pobierana za korzystanie z api.
|
||||
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
|
||||
API.
|
||||
|
||||
Dla każdej parafii wykonywane jest zapytanie do serwisu \textit{Text Search}
|
||||
składające się z konkatenacji nazwy, parafii, jej miejscowości i ulicy na której
|
||||
się znajduje. Jeśli nie zostanie znaleziony żaden obiekt wysyłane jest powtórne
|
||||
składające się z konkatenacji nazwy, parafii, jej miejscowości i ulicy, na której
|
||||
się znajduje. Jeśli nie zostanie znaleziony żaden obiekt, wysyłane jest powtórne
|
||||
zapytanie, lecz tym razem składające się tylko z nazwy parafii i jej
|
||||
miejscowości. Zdarza się, że \textit{Text Search} zwraca kilka obiektów. W takim
|
||||
przypadku brany jest adres url pierwszego obiektu z listy wyników.
|
||||
miejscowości. Zdarza się, że serwis \textit{Text Search} zwraca kilka obiektów. W takim
|
||||
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.
|
||||
|
||||
Powyższą metodą udało się zebrać adresy url dla ok. 5600 parafii.
|
||||
adres internetowy. Taki przypadek przedstawia rysunek \ref{pic:text_search}.
|
||||
Serwis \textit{Text Search} zwraca dużo danych w formacie \textit{json}, które
|
||||
ciężko przedstawić w przejrzystej postaci.
|
||||
Dla
|
||||
czytelności na rysunku \ref{pic:text_search} pokazano zrzuty z wyszukiwarki \textit{Google Maps},
|
||||
które odpowiadają rezultatowi jaki otrzymanoby korzystając z serwisu
|
||||
\textit{Text Search}.
|
||||
|
||||
\noindent Powyższą metodą udało się zebrać adresy URL dla ok. 5600 parafii.
|
||||
|
||||
\begin{figure}[tbh]
|
||||
\center
|
||||
\includegraphics[width=1\hsize]{amb_text_search.png}
|
||||
\caption{Przykład dwóch obiektów zwróconych przez \textit{Text Search}, które
|
||||
\caption{Przykład dwóch obiektów zwróconych przez wyszukiwarkę Google, które
|
||||
mają ten sam adres internetowy.}
|
||||
\label{text_search_pic}
|
||||
\label{pic:text_search}
|
||||
\end{figure}
|
||||
|
||||
|
||||
|
||||
\section{Crawlowanie stron parafialnych}
|
||||
|
||||
\begin{figure}[tbh]
|
||||
\section{Indeksowanie stron parafialnych}
|
||||
\enlargethispage{1\baselineskip}
|
||||
\begin{figure}[htb!]
|
||||
\center
|
||||
\includegraphics[width=0.7\hsize]{crawler_parafii_general_trans.png}
|
||||
\label{crawler_parafii_general_pic}
|
||||
\caption{Fragment architektury systemu przedstawiający komponent odpowiedzialny
|
||||
za indeksowanie stron parafialnych.}
|
||||
\label{pic:pajak_parafii_general}
|
||||
\end{figure}
|
||||
Crawler został napisany przy użyciu biblioteki Scrapy.
|
||||
Punktem startowym jest pojedynczy adres url parafii podawany na wejście
|
||||
programu. Z początkowego adresu url wydobywana jest domena w obrębie której
|
||||
porusza się pająk. Oznacza to, że jedna instancja pająka zajmuje się ściąganiem
|
||||
tylko jedenej parafii. W ramach jednej parafii pająk jest w stanie
|
||||
|
||||
|
||||
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.
|
||||
|
||||
Pająk został napisany przy użyciu biblioteki \textit{Scrapy}\cite{scrapy}.
|
||||
Punktem startowym jest pojedynczy adres URL parafii podawany na wejście
|
||||
programu. Z początkowego adresu URL wydobywana jest domena, w której obrębie
|
||||
porusza się pająk. Oznacza to, że jedna instancja pająka zajmuje się pobieraniem
|
||||
tylko jednej parafii. W ramach jednej parafii pająk jest w stanie
|
||||
asynchronicznie wysłać wiele zapytań do serwera i odbierać wiele odpowiedzi od serwera.
|
||||
|
||||
\subsection{Komponenty pająka}
|
||||
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 [Downloader] -- jego zadniem jest ściąganie stron parafialnych i
|
||||
\item [Downloader] -- odpowiada za pobieranie stron parafialnych i
|
||||
przekazywanie ich silnikowi.
|
||||
\item [Przetwarzacz danych] -- zajmuje się końcową obróbką i zapisem danych.
|
||||
\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 crawlowanie stron parafialnych).}
|
||||
- definuje sposób w jaki ściągać dane, między innymi jak parsować stronę i za jakimi
|
||||
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 silnkiem, a
|
||||
spider'em. Odpowiedzialne są za dodatkowe przetwarzanie danych wyjściowych
|
||||
(dane parafialne i żądania) i wejściowych (odpowiedzi) spider'a.
|
||||
\item [Spider middleware] -- programy pośredniczące między 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
|
||||
downloader'em. Zajmują się dodatkowym przetwarzaniem danych wejściowych
|
||||
(żądań) i wyjściowych (odpowiedzi) downloader'a.
|
||||
\textit{downloader'em}. Zajmują się dodatkowym przetwarzaniem danych wejściowych
|
||||
(żądań) i wyjściowych (odpowiedzi) \textit{downloader'a}.
|
||||
|
||||
\end{description}
|
||||
\newpage
|
||||
\subsection{Przepływ danych}
|
||||
|
||||
Przepływ danych kontrolowany jest przez
|
||||
silnik i prezentuje się następująco\footnote{Diagram i opis wzorowany jest na
|
||||
dokumentacji znajdującej się pod linkiem https://doc.scrapy.org/en/latest/topics/architecture.html}:
|
||||
silnik i wygląda następująco\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]
|
||||
\center
|
||||
\includegraphics[width=0.85\hsize]{scrapy_data_flow.png}
|
||||
% \caption{100 crawlerów pracujących jednocześnie}
|
||||
\label{scrapy_data_flow_pic}
|
||||
\caption{Silnik kontrolujący przepływ danych przez komponenty pająka.}
|
||||
\label{pic:scrapy_data_flow}
|
||||
\end{figure}
|
||||
|
||||
\begin{enumerate}
|
||||
\item Silnik otrzymuje od spider'a żądanie pobrania początkowej strony danej
|
||||
\item 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 downloader'owi.
|
||||
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 downloader'a. Zanim żądania dotrą do
|
||||
downloader'a przetwarzane są przez downloader middleware.
|
||||
\item Downloader ściąga stronę parafialną i umieszcza ją w odpowiedzi, którą
|
||||
przesyła silnikowi. Zanim odpowiedź dotrze do silnka przetwarzana jest przez
|
||||
downloader middleware.
|
||||
\item Silnik otrzymuje odpowiedź od downloader'a i przekazuje ją spider'owi do
|
||||
dalszego przetwarzania. Zanim odpowiedź trafi do spider'a przetwarzana jest
|
||||
przez spider middleware.
|
||||
\item Spider przerabia odpowiedź i zwraca dane strony parafialnej silnikowi. Zanim dane
|
||||
trafią do silnika przechodzą przez spider middleware. Dodatkowo spider
|
||||
wysła żądania z nowymi stronami parafialnymi do pobrania.
|
||||
\item Silnik wysyła zebrane dane do przetwarzacza danych, który zapisuje je w
|
||||
pliku jsonline\cite{jsonline}. Następnie przekazuje nowe żądania do zakolejkowania
|
||||
\item 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
|
||||
\textit{downloader middleware}.
|
||||
\item 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}
|
||||
wysyła żądania z nowymi stronami parafialnymi do pobrania.
|
||||
\item Silnik wysyła zebrane dane do procesora danych, który zapisuje je do
|
||||
pliku.. Następnie przekazuje nowe żądania do zakolejkowania
|
||||
dyspozytorowi.
|
||||
\end{enumerate}
|
||||
% \vspace*{-20mm}
|
||||
Cały proces trwa dopóty, dopóki są nowe żądania do przetworzenia.
|
||||
|
||||
\subsection{Sprawdzanie typu odpowiedzi}
|
||||
Podczas crawlowania ważne jest rozpoznawanie typu ściąganych danych. W przypadku
|
||||
crawlowania stron parafialnych interesują nas wyłącznie dane tekstowe. Należy
|
||||
Podczas indeksowania ważne jest rozpoznawanie typu pobieranych danych. W przypadku
|
||||
indeksowania stron parafialnych interesują nas wyłącznie dane tekstowe. Należy
|
||||
zatem zadbać o to, aby nie pobierać danych binarnych takich jak np. video, audio
|
||||
i obrazy.
|
||||
|
||||
Scrapy obsługuje rozpoznawanie typu zawartości odpowiedzi bazując na
|
||||
Biblioteka \textit{Scrapy} obsługuje rozpoznawanie typu zawartości odpowiedzi, bazując na
|
||||
następujących kryteriach:
|
||||
\begin{itemize}
|
||||
\item wartościach \mintinline{bash}{Content-type}\cite{RFC2045}, \mintinline{bash}{Content-Encoding}\cite{RFC7231} i \mintinline{bash}{Content-Disposition}\cite{RFC6266} w nagłówku odpowiedzi,
|
||||
\item nazwie pliku lub adresie url (jeśli nie udało się rozpoznać po nagłówku),
|
||||
\item analizując pierwsze 5000 bajtów zawartości odpowiedzi w poszukiwaniu
|
||||
znaków znajdującyh się wyłącznie w plikach binarnych (jeśli nie udało się
|
||||
rozpoznać po nazwie pliku lub adresie url).
|
||||
\item wartości \mintinline{bash}{Content-type}\cite{RFC2045}, \mintinline{bash}{Content-Encoding}\cite{RFC7231} i \mintinline{bash}{Content-Disposition}\cite{RFC6266} w nagłówku odpowiedzi,
|
||||
\item nazwie pliku lub adresie URL (jeśli nie udało się rozpoznać po nagłówku),
|
||||
\item obecności znaków kontrolnych w pierwszych 5000 bajtów odpowiedzi
|
||||
(jeśli nie udało się
|
||||
rozpoznać po nazwie pliku lub adresie URL).
|
||||
\end{itemize}
|
||||
Powyższy schemat postępowania jest skuteczny jeśli serwisy internetowe zwracają
|
||||
Powyższy schemat postępowania jest skuteczny, jeśli serwisy internetowe zwracają
|
||||
poprawne odpowiedzi. Niestety niektóre strony parafialne potrafią zwracać
|
||||
odpowiedzi, które są niezgodne z rozdziałem 3.1 z RFC7231\cite{RFC7231}.
|
||||
Dla przykładu, strona potrafi zwrócić \mintinline{bash}{Content-Type: text/html}, a w \mintinline{bash}{body} binarną
|
||||
odpowiedzi, które nie są zgodne z rozdziałem 3.1 z RFC7231\cite{RFC7231}.
|
||||
Dla przykładu strona potrafi zwrócić \mintinline{bash}{Content-Type: text/html}
|
||||
w nagłówku, a w ciele binarną
|
||||
zawartość np. film. Tego rodzaju anomalie są wykrywane i eliminowane.
|
||||
Stosując następujący algorytm\cite{binaryornot} można określić typ zawartości \mintinline{bash}{body}:
|
||||
\enlargethispage{2\baselineskip}
|
||||
Stosując algorytm \ref{alg:binaryornot}, można określić typ zawartości
|
||||
ciała odpowiedzi.
|
||||
|
||||
|
||||
\enlargethispage{4\baselineskip}
|
||||
\begin{algorithm}
|
||||
\begin{algorithm}[tbh!]
|
||||
\setstretch{1.2}
|
||||
\SetAlgorithmName{Algorytm}{algorithm}{List of Algorithms}
|
||||
\caption{Rozpoznawanie plików binarnych}
|
||||
\label{alg:binaryornot}
|
||||
\SetKwIF{IfM}{ElseIfM}{ElseM}{if~(\endgraf}{\endgraf\nl)~then}{else
|
||||
if}{else}{\nl end if}%
|
||||
\SetKwIF{If}{ElseIf}{Else}{if}{then}{else if}{else}{\nl end if}%
|
||||
\SetAlgoLined
|
||||
\SetKwData{File}{bytes}
|
||||
\SetKwData{True}{True}
|
||||
@ -248,105 +332,220 @@ Stosując następujący algorytm\cite{binaryornot} można określić typ zawarto
|
||||
|
||||
\SetKwData{ControlCount}{control\_char\_count}
|
||||
\SetKwData{ControlRatio}{control\_char\_ratio}
|
||||
\SetKwData{AsciiCount}{extended\_ascii\_count}
|
||||
\SetKwData{AsciiRatio}{extended\_ascii\_ratio}
|
||||
\If{\File puste}{
|
||||
\Return{\False}\;
|
||||
}
|
||||
\If{\File dekodowalne jako unikod}{
|
||||
\Return{\False}\;
|
||||
}
|
||||
\ControlCount $\leftarrow$ liczba znaków kontrolnych w \File\;
|
||||
\AsciiCount $\leftarrow$ liczba znaków ascii o kodach od 128 do 255 w \File\;
|
||||
\ControlRatio $\leftarrow \frac{\ControlCount}{1024}$\;
|
||||
\AsciiRatio $\leftarrow \frac{\AsciiCount}{1024}$\;
|
||||
|
||||
\SetKwIF{IfM}{ElseIfM}{ElseM}{if~(\endgraf}{\endgraf)~then}{else if}{else}{end if}%
|
||||
\IfM{\begin{tabular}{@{\hspace*{1.5em}}l@{}}
|
||||
$($\ControlRatio $> 0.3$ {\bf and} \AsciiRatio $< 0.05)$ {\bf or}\\
|
||||
$($\ControlRatio $> 0.8$ {\bf and} \AsciiRatio $> 0.80)$
|
||||
\end{tabular}}{
|
||||
\Return{\True}\;
|
||||
}
|
||||
|
||||
\SetKwData{AsciiCount}{high\_ascii\_count}
|
||||
\SetKwData{AsciiRatio}{high\_ascii\_ratio}
|
||||
\SetKwData{Null}{null}
|
||||
\If{znak \Null w \File}{
|
||||
\Return{\True}\;
|
||||
\nl\uIf{\File puste {\bf or} \File dekodowalne jako unikod}{
|
||||
\nl \Return{\False}\;
|
||||
}\ElseIf{znak \Null \bf in \File}{
|
||||
\nl \Return{\True}\;
|
||||
}
|
||||
\Return{\False}\;
|
||||
\nl \tcc{Za znaki kontrolne uznajemy znaki o kodach EASCII od 0 do 7, 11, od 14
|
||||
do 32 i od 127 do 159.}
|
||||
\nl\ControlCount $\leftarrow$ liczba znaków kontrolnych w \File\;
|
||||
\nl\AsciiCount $\leftarrow$ liczba znaków EASCII o kodach od 160 do 255 w \File\;
|
||||
\nl\ControlRatio $\leftarrow \frac{\ControlCount}{1024}$\;
|
||||
\nl\AsciiRatio $\leftarrow \frac{\AsciiCount}{1024}$\;
|
||||
\nl \If{$($\ControlRatio $> 0.3$ {\bf or} \AsciiRatio $> 0.7)$}{
|
||||
\nl \Return{\True}\;
|
||||
}
|
||||
\nl \Return{\False}\;
|
||||
\end{algorithm}
|
||||
\subsection{Automatyczna regulacja częstości zapytań}
|
||||
Biblioteka scrapy zawiera przydatne rozszerzenie, które potrafi automatycznie
|
||||
regulować częstość zapytań w zależności od obciążenia crawler'a i strony internetowej.
|
||||
|
||||
\noindent Algorytym regulacji częstości zapytań prezentuje się następująco:
|
||||
Algorytm \ref{alg:binaryornot} analizuje zawartość ciała odpowiedzi w celu
|
||||
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
|
||||
o kodach od 128 do 159. Zostały zdefiniowane w standardzie ISO/IEC 2022.
|
||||
Wiele
|
||||
innych systemów kodowań rezerwuje sobie kody od 128 do 159 na znaki kontrolne.} z wyłączeniem
|
||||
następujących znaków:
|
||||
\begin{itemize}
|
||||
\item znak nowej linii (oznaczany przez \mintinline{python}{\n}),
|
||||
\item znak powrotu karetki (oznaczany przez \mintinline{python}{\r}),
|
||||
\item znak tab (oznaczany przez \mintinline{python}{\t}),
|
||||
\item znak backspace (oznaczany przez \mintinline{python}{\b}),
|
||||
\item znak nowej linii (oznaczany przez \mintinline{python}{\n}),
|
||||
\item znak końca strony (oznaczany przez \mintinline{python}{\f}),
|
||||
\end{itemize}
|
||||
Powyższe znaki zostały wykluczone, ponieważ często występują w plikach tekstowych.
|
||||
|
||||
Warto zwrócić uwagę na linię 10. Współczynnik
|
||||
\mintinline{python}{control_char_ratio}
|
||||
oznacza procent znaków kontrolnych w pierszych 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
|
||||
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
|
||||
procent znaków EASCII\footnote{EASCII
|
||||
oznacza rozszerzone kodowanie ASCII. Przykładowe rozszrzenia to systemy
|
||||
kodowania ISO 8859 lub UTF-8.}
|
||||
o kodach od 160 do 255.
|
||||
Reprezentacja tych znaków zależy od rozszerzenia ASCII. Najczęściej jednak są to
|
||||
znaki drukowalne, które rzadko występują w tekście.
|
||||
Jeśli współczynnik \mintinline{python}{high_ascii_ratio} jest większy niż $0.7$
|
||||
to plik jest uznawany za binarny.
|
||||
Wartośc $0.7$ została dobrana na podstawie następujących obserwacji:
|
||||
\begin{enumerate}
|
||||
\item Przyjmijmy, że:
|
||||
|
||||
\subitem {\makebox[4.55cm][l]{\mintinline{python}{download_delay}}} to opóźnienie\footnote{Czasy oczekiwania i
|
||||
opóźnienia liczone są w sekudnach.} wysłania
|
||||
zapytania.
|
||||
\subitem \mintinline{python}{target_download_delay} to docelowe
|
||||
opóźnienie zapytania.
|
||||
\subitem {\makebox[4.55cm][l]{\mintinline{python}{init_download_delay}}} to początkowe opóźnienie wysłania
|
||||
zapytania.
|
||||
\subitem {\makebox[4.55cm][l]{\mintinline{python}{min_download_delay}}} to minimalne opóźnienie wysyłania.
|
||||
\subitem {\makebox[4.55cm][l]{\mintinline{python}{max_download_delay}}} to maksymalne opóźnienie wysyłania.
|
||||
\subitem {\makebox[4.55cm][l]{\mintinline{python}{latency}}} to czas od
|
||||
ustanowienia połączenia \\
|
||||
{\makebox[5.22cm][l]{}} do otrzymania nagłówków odpowiedzi.
|
||||
\subitem {\makebox[4.55cm][l]{\mintinline{python}{target_concurrency}}} to zaplanowana liczba zapytań na sekundę.
|
||||
|
||||
\item Zacznij z \mintinline{python}{download_delay} równym \mintinline{python}{init_download_delay}.
|
||||
\item Kiedy odpowiedź jest odebrana, \\ustaw
|
||||
\mintinline{python}{target_download_delay = latency / target_concurrency}.
|
||||
\item Następne \mintinline{python}{download_delay} ustaw jako średnią z
|
||||
aktualnego \mintinline{python}{download_delay} i \mintinline{python}{target_download_delay}.
|
||||
\item \mintinline{python}{download_delay} nie może być mniejszy niż
|
||||
\mintinline{python}{min_download_delay} i większy niż \mintinline{python}{max_download_delay}.
|
||||
\item Czasy oczekiwania na odpowiedzi z kodem http różnym od 2xx nie są brane
|
||||
pod uwagę.
|
||||
\item Zdarzają się pliki binarne, które mają dużo znaków
|
||||
\mintinline{python}{high_ascii}. Przykładem jest plik z katalogu
|
||||
\mintinline{text}{data.tar.gz/spec/resources/pixelstream.rgb}
|
||||
z archiwum \url{https://rubygems.org/downloads/chunky\_png-1.2.8.gem}. Plik
|
||||
zawiera bardzo dużo znaków o kodzie 255 w początkowych bajtach.
|
||||
\item Mało prawdopodobne jest, aby plik tekstowy miał w pierwszych 1024 bajtach
|
||||
więcej niż 70\% znaków \mintinline{python}{high_ascii}. Nawet jeśli pająk
|
||||
natrafiłby na taki plik to z dużym prawdopodbieństwem nie zawierałby on
|
||||
informacji parafialnych.
|
||||
\end{enumerate}
|
||||
|
||||
\noindent W crawlerze stron parafialnych stałe ustawiono następująco:
|
||||
\subsection{Automatyczna regulacja częstości zapytań}
|
||||
Biblioteka \textit{Scrapy} zawiera przydatne rozszerzenie, które potrafi automatycznie
|
||||
regulować częstość zapytań w zależności od obciążenia pająka i strony internetowej.
|
||||
|
||||
Algorytm \ref{alg:throttling} przedstawia sposób postępowania w jaki pająk
|
||||
automatycznie reguluje częstość zapytań. Idea algorytmu jest następująca.
|
||||
Załóżmy, że serwer potrzebuje
|
||||
\mintinline{python}{latency}\footnote{Zmienna \mintinline{python}{latency}
|
||||
została
|
||||
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 powinnien
|
||||
wysyłać każde zapytanie co \mintinline{python}{latency/target_concurrency}
|
||||
sekund.
|
||||
|
||||
\begin{algorithm}[tbh!]
|
||||
\setstretch{1.2}
|
||||
\SetAlgorithmName{Algorytm}{algorithm}{List of Algorithms}
|
||||
\caption{Algorytm regulacji częstości zapytań}
|
||||
\label{alg:throttling}
|
||||
\SetAlgoLined
|
||||
\SetKwFunction{Request}{send\_request}
|
||||
\SetKwData{Delay}{download\_delay}
|
||||
\SetKwData{tDelay}{target\_download\_delay}
|
||||
\SetKwData{iDelay}{init\_download\_delay}
|
||||
\SetKwData{minDelay}{min\_download\_delay}
|
||||
\SetKwData{maxDelay}{max\_download\_delay}
|
||||
\SetKwData{latency}{latency}
|
||||
\SetKwData{targetConcurrency}{target\_concurrency}
|
||||
\SetKwInput{kwConst}{Stałe}
|
||||
\SetKwInput{kwVar}{Zmienne}
|
||||
\SetKwInput{kwWhere}{gdzie}
|
||||
\SetKwInput{kwAlg}{Algorytm}
|
||||
\kwConst{\\
|
||||
\Indp{\makebox[4.1cm][l]{\iDelay}} $-$ początkowe opóźnienie wysłania zapytania. \\
|
||||
{\makebox[4.1cm][l]{\minDelay}} $-$ minimalne opóźnienie wysłania zapytania. \\
|
||||
{\makebox[4.1cm][l]{\maxDelay}} $-$ maksymalne opóźnienie wysłania zapytania.\\
|
||||
{\makebox[4.1cm][l]{\targetConcurrency}} $-$ średnia wartość równoległych
|
||||
zapytań do
|
||||
\phantom{{\makebox[4.1cm][l]{\targetConcurrency}} $-$} wysłania.
|
||||
}
|
||||
\kwVar{\\
|
||||
\Indp{\makebox[4.1cm][l]{\tDelay}} $-$ docelowe opóźnienie wysyłania zapytania.\\
|
||||
{\makebox[4.1cm][l]{\Delay}} $-$ opóźnienie wysłania zapytania. \\
|
||||
{\makebox[4.1cm][l]{\latency}} $-$ czas od ustanowienia połączenia do
|
||||
\phantom{{\makebox[4.1cm][l]{\latency}} $-$} otrzymania nagłówków odpowiedzi.
|
||||
}
|
||||
\bigskip
|
||||
\kwAlg{
|
||||
\begin{enumerate}[rightmargin=5mm]
|
||||
\item Wyślij zapytanie do serwisu;
|
||||
\item Ustaw $\Delay \leftarrow \iDelay$.
|
||||
\item Gdy odebrano odpowiedź, ustaw
|
||||
$\tDelay \leftarrow \frac{\latency}{\targetConcurrency}$.
|
||||
\item Ustaw $\Delay \leftarrow \frac{\Delay\ +\ \tDelay}{2}$
|
||||
\item Czekaj \Delay sekund.
|
||||
\item Wyślij kolejne zapytanie do serwisu;
|
||||
\item Wróć do kroku nr 3.
|
||||
\end{enumerate}
|
||||
}
|
||||
\kwWhere{
|
||||
\begin{itemize}
|
||||
\item Opóźnienia liczone są w sekundach.
|
||||
\item \Delay nie może być mniejszy niż \minDelay i większy niż \maxDelay.
|
||||
\item Czasy oczekiwania na odpowiedzi z kodem http różnym od 2xx nie są brane
|
||||
pod uwagę.
|
||||
\item Algorytm kończy się, gdy nie ma więcej zapytań do wysłania.
|
||||
\end{itemize}
|
||||
}
|
||||
\end{algorithm}
|
||||
|
||||
\clearpage
|
||||
\noindent W pająku stron parafialnych stałe z algorytmu \ref{alg:throttling} ustawiono następująco:
|
||||
|
||||
\begin{itemize}
|
||||
\item \mintinline{python}{min_download_delay = 0}
|
||||
\item \mintinline{python}{max_download_delay = 300}
|
||||
\item \mintinline{python}{init_download_delay = 5}
|
||||
\item \mintinline{python}{target_concurrency = 1}
|
||||
\end{itemize}
|
||||
Stałe \mintinline{python}{min_download_delay} i
|
||||
\mintinline{python}{max_download_delay} zostały ustawione w taki sposób, aby nie
|
||||
ograniczać zbyt mocno
|
||||
pająka co do doboru wartości \mintinline{python}{download_delay}. Celem jest
|
||||
przecież automatyczna regulacja wartości \mintinline{python}{download_delay}.
|
||||
Niska wartość stałej \mintinline{python}{target_concurrency} umotywowana jest
|
||||
dużą liczbą równolegle pracujących pająków (patrz podrozdział \ref{subsec:multiprocess}).
|
||||
|
||||
|
||||
\subsection{Crawlowanie wieloprocesorowe}
|
||||
\subsection{Indeksowanie wieloprocesorowe}
|
||||
\label{subsec:multiprocess}
|
||||
\begin{figure}[tbh!]
|
||||
\center
|
||||
\includegraphics[width=0.72\hsize]{crawler.png}
|
||||
\caption{100 crawlerów pracujących jednocześnie.}
|
||||
\label{crawler_pic}
|
||||
\caption{100 pająków pracujących jednocześnie.}
|
||||
\label{pic:pajaki}
|
||||
\end{figure}
|
||||
Pająk został zaprojektowany w ten sposób, aby bardzo łatwo można było
|
||||
urównoleglić ściąganie stron parafialnych.
|
||||
Z pomocą GNU parallel\cite{parallel} crawlowane jest jednocześnie 100 parafii. Gdy jedna ze stu
|
||||
parafii zostanie ściągnięta, zastępuje ją kolejna parafia. Tym sposobem przez
|
||||
prawie cały czas równolegle pracuje 100 crawlerów. Takie podejście pozwoliło
|
||||
urównoleglić pobieranie stron parafialnych.
|
||||
Z pomocą programu \textit{GNU parallel}\cite{parallel} indeksowane jest
|
||||
jednocześnie 100 parafii (patrz rys. \ref{pic:pajaki}). Gdy jedna ze stu
|
||||
parafii zostanie pobrana, zastępuje ją kolejna parafia. Tym sposobem przez
|
||||
prawie cały czas równolegle pracuje 100 pająków. Takie podejście pozwoliło
|
||||
maksymalnie wykorzystać łącze internetowe, które było wąskim gardłem w procesie
|
||||
crawlowania stron parafialnych.
|
||||
|
||||
indeksowania stron parafialnych.
|
||||
|
||||
\subsection{Organizacja danych}
|
||||
Mały podrozdział do zrobienia lub pominięcia.
|
||||
Dane zbierane przez pająka zapisywane są do pliku w formacie \textit{JSON
|
||||
Lines}. Format \textit{JSON Lines} charakteryzuje się tym, że w każdej linii pliku
|
||||
znajduje się poprawny obiekt \textit{json}.
|
||||
Dla
|
||||
każdej parafii pobrane dane zapisywane są w oddzielnym pliku. W każdej linii
|
||||
pliku znajduje się strona parafialna zapisana w formacie \textit{json}.
|
||||
Zapis w formacie \textit{JSON Lines} i traktowanie każdej linii jako strony parafialnej niesie szereg korzyści takich jak:
|
||||
\begin{enumerate}
|
||||
\item wygodne przetwarzanie równoległe,
|
||||
\item łatwa obróbka danych za pomocą narzędzi Unixowych,
|
||||
\item mniejszy rozmiar pliku w porównaniu do zwykłego formatu \textit{json}.
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Konwersja html na tekst.}
|
||||
\begin{figure}[tbh]
|
||||
\noindent Dla każdej strony parafialnej zapisywane są następujące informacje:
|
||||
\begin{enumerate}
|
||||
\item adres URL strony,
|
||||
\item adres URL poprzedniej strony,
|
||||
\item adres URL strony początkowej,
|
||||
\item domena parafii,
|
||||
\item strona parafii w formacie HTML,
|
||||
\item tekst z odnośnika (linku), który doprowadził do bieżącej strony.
|
||||
\end{enumerate}
|
||||
|
||||
\section{Konwersja HTML na tekst.}
|
||||
\begin{figure}[tbh!]
|
||||
\center
|
||||
\includegraphics[width=0.6\hsize]{html2text_trans.png}
|
||||
\label{hmlt2text_pic}
|
||||
\includegraphics[width=0.53\hsize]{html2text_trans.png}
|
||||
\caption{Fragment architektury systemu przedstawiający komponent odpowiedzialny
|
||||
za konwersje HTML na tekst.}
|
||||
\label{pic:html2text}
|
||||
\end{figure}
|
||||
|
||||
Do konwersji z formatu html na format tekstowy wykorzystano bibliotekę \mintinline{bash}{html2text}\cite{html2text}
|
||||
pierwotnie rozwijaną przez słynnego programistę Aarona Schwartza.
|
||||
\mintinline{bash}{html2text} konwertuje html na czysty, czytelny tekst w
|
||||
formacie Markdown\cite{markdown}. Biblioteka oferuje wiele opcji do kontroli
|
||||
Na rysunku \ref{pic:html2text} został przedstawiony fragment architektury
|
||||
systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w tym podrozdziale.
|
||||
|
||||
Do konwersji z formatu HTML na format tekstowy wykorzystano bibliotekę \mintinline{bash}{html2text}\cite{html2text}
|
||||
pierwotnie rozwijaną przez Aarona Schwartza.
|
||||
\mintinline{bash}{html2text} konwertuje HTML na czysty, czytelny tekst w
|
||||
formacie \textit{Markdown}\cite{markdown}. Biblioteka oferuje wiele opcji do kontroli
|
||||
konwersji i jest bardzo łatwa w modyfikacji.
|
||||
|
||||
\smallskip
|
||||
@ -355,26 +554,32 @@ konwersji i jest bardzo łatwa w modyfikacji.
|
||||
\begin{itemize}
|
||||
% \setlength{\itemsep}{1pt}
|
||||
\item ignorowanie linków, tabel i obrazków,
|
||||
\item usunięto znaki odpowiedzialne za pogrubienie i kurysywę tekstu,
|
||||
\item usunięto znaki odpowiedzialne za tworzenie list.
|
||||
\item usuwanie znaków odpowiedzialne za pogrubienie i kursywę tekstu,
|
||||
\item usuwanie znaków odpowiedzialne za tworzenie list.
|
||||
\end{itemize}
|
||||
|
||||
\section{Ekstraktor godzin}
|
||||
\section{Ekstrakcja godzin}
|
||||
\begin{figure}[tbh!]
|
||||
\center
|
||||
\includegraphics[width=0.6\hsize]{general_ekstraktor.png}
|
||||
\label{general_ekstraktor_pic}
|
||||
\includegraphics[width=0.65\hsize]{general_ekstraktor.png}
|
||||
\caption{Fragment architektury systemu przedstawiający komponent odpowiedzialny
|
||||
za ekstrakcję godzin ze stron parafialnych.}
|
||||
\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.
|
||||
|
||||
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ł
|
||||
bardzo wysoki recall, ale już niekoniecznie wysoką precyzję.
|
||||
bardzo wysoką wartość pokrycia, ale już niekoniecznie wysoką precyzję.
|
||||
Celem jest,
|
||||
aby w zbiorze wykestrahowanych godzin znalazło się jak najwięcej godzin
|
||||
rozpoczęcia mszy, bez względu na to jak duży jest ten zbiór.
|
||||
aby w zbiorze wyekstrahowanych godzin znalazło się jak najwięcej godzin
|
||||
rozpoczęcia mszy, bez względu na to, jak duży jest ten zbiór. Ekstraktor wraz
|
||||
ze znalezioną godziną zapisuje kontekst w jakim ta godzina się znalazła.
|
||||
|
||||
Do osiągnięcia tego celu zastosowano następujące reguły.
|
||||
Ciąg znaków oznaczony jako \mintinline{bash}{hour} zostanie wyekstrahowany, jeśli
|
||||
zajdzie każdy z poniżych warunków:
|
||||
zajdzie każdy z poniższych warunków:
|
||||
\begin{enumerate}
|
||||
\item \mintinline{bash}{hour} pasuje do wyrażenia regularnego \\ \mintinline{text}{(0?[6-9]|1\d|2[0-2])[:.](oo|[0-5]\d)|6|7|8|9|1\d|2[0-2]};
|
||||
\item Znak przed \mintinline{bash}{hour} zawiera się w
|
||||
@ -382,19 +587,109 @@ zajdzie każdy z poniżych warunków:
|
||||
\item Znak po \mintinline{bash}{hour} zawiera się w
|
||||
\mintinline{python}{{',', ')', ';'}};
|
||||
\item Jeśli znak przed \mintinline{bash}{hour} równa się
|
||||
\mintinline{python}{'('} to znak po \mintinline{bash}{hour} jest różny od \mintinline{bash}{')'}.
|
||||
\mintinline{python}{'('}, to znak po \mintinline{bash}{hour} jest różny od \mintinline{bash}{')'}.
|
||||
\end{enumerate}
|
||||
|
||||
\section{Filtrowanie stron}
|
||||
\begin{figure}[tbh!]
|
||||
\center
|
||||
\includegraphics[width=0.5\hsize]{filtrowanie.png}
|
||||
\caption{Fragment architektury systemu przedstawiający komponent odpowiedzialny
|
||||
za filtrowanie stron parafialnych.}
|
||||
\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.
|
||||
|
||||
\section{System crowdsourcingowy}
|
||||
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
|
||||
potrzebny, aby ograniczyć liczbę godzin, które trafią do anotatora. Gdyby nie zastosowano
|
||||
filtru stron parafialnych ekstraktor godzin wśród wszystkich stron parafialnych
|
||||
znalazłby ponad 3 miliony godzin. Po zaaplikowaniu filtru stron i przetworzeniu
|
||||
ich przez ekstraktor godzin otrzymano 10920 godzin. Później godziny wraz z
|
||||
kontekstami poddawane są anotacji. Etap ten będzie dokładniej opisany w kolejnym podrozdziale.
|
||||
|
||||
Reguły zastosowane do zadecydowania czy dana strona zawiera godziny mszy
|
||||
świętych zostały przedstawione w
|
||||
algorytmie \ref{alg:has_mass}.
|
||||
\begin{algorithm}
|
||||
\setstretch{1.2}
|
||||
\SetAlgorithmName{Algorytm}{algorithm}{List of Algorithms}
|
||||
\caption{Rozpoznawanie stron z godzinami mszy świętych.}
|
||||
\label{alg:has_mass}
|
||||
\SetKwIF{IfM}{ElseIfM}{ElseM}{if~(\endgraf}{\endgraf\nl)~then}{else
|
||||
if}{\nl else}{\nl end if}%
|
||||
\SetKwIF{If}{ElseIf}{Else}{if}{then}{else if}{else}{\nl end if}%
|
||||
\SetAlgoLined
|
||||
\SetKwData{url}{url}
|
||||
\SetKwData{bText}{btn\_text}
|
||||
\SetKwData{False}{False}
|
||||
\SetKwData{True}{True}
|
||||
\SetKwInput{kwInput}{Wejście}
|
||||
\SetKwInput{kwOutput}{Wyjście}
|
||||
\kwInput{\\
|
||||
\vspace{-0.5mm}
|
||||
\Indp\url $\leftarrow$ adres internetowy analizowanej strony,\\
|
||||
\bText $\leftarrow$ tekst na przycisku, który doprowadził do
|
||||
analizowanej \phantom{\bText $\leftarrow$} strony.
|
||||
}
|
||||
|
||||
\kwOutput{
|
||||
\vspace{-2mm}
|
||||
\begin{itemize}[rightmargin=5mm]
|
||||
\setlength\itemsep{-1mm}
|
||||
\item \True jeśli jest wysokie prawdopodbieństwo, że strona zawiera godziny mszy
|
||||
\item \False jeśli jest niskie prawdopodbieństwo, że strona zawiera godziny mszy
|
||||
\end{itemize}
|
||||
}
|
||||
|
||||
\SetKwData{suf}{url\_suf}
|
||||
\SetKwData{slash}{'/'}
|
||||
\SetKwData{goodreg}{ok\_regex}
|
||||
\SetKwData{badreg}{bad\_regex}
|
||||
|
||||
\nl\tcc{Wyrażenia regularne \goodreg i \badreg ignorują wielkość liter.}
|
||||
\nl $\goodreg \leftarrow$
|
||||
\mintinline[breaklines]{python}{'msze|nabo[żz]e[ńn]stw(a|(?=\W\d)|$)|
|
||||
porz[ąa]dek($|\.htm)|porz[aą]dek.(liturgi|mszy)| (rozk[lł]ad|plan|godziny|uk[lł]ad|harmonogram|grafik|rozpiska).mszy'}
|
||||
|
||||
\medskip \vspace{-1mm}
|
||||
\nl $\badreg \leftarrow$
|
||||
\mintinline[breaklines]{python}{'nabo[zż]e[nń]stwa.(majowe|wielk|czerwcowe |maryjne|pasyjne|pokutne|fatimskie|do|ro[żz]a|czterdzie|w.wielk)'}
|
||||
|
||||
\nl$\suf \leftarrow$ ciąg znaków w \url po ostatnim wystąpieniu \slash\;
|
||||
|
||||
\nl\uIfM{\begin{tabular}{@{\hspace*{-3.8pt}}l@{}}
|
||||
\nl \hspace*{1.2em}
|
||||
$($ \suf pasuje do $\goodreg$ {\bf and} \suf nie pasuje do \badreg $)$ {\bf or}\\
|
||||
\nl \hspace*{1.2em}
|
||||
$($ \bText pasuje do $\goodreg$ {\bf and} \bText nie pasuje do \badreg $)$
|
||||
\end{tabular}}{
|
||||
\nl \Return{\True};\
|
||||
}\ElseM{
|
||||
\Return{\False};\
|
||||
}
|
||||
\end{algorithm}
|
||||
|
||||
W algorytmie \ref{alg:has_mass} warto zwórcić uwagę na wyrażenia regularne
|
||||
\mintinline{text}{ok_regex} i \mintinline{text}{bad_regex}. Wyrażenie
|
||||
regularne \mintinline{text}{ok_regex} ma za zadanie dopasować się do słów,
|
||||
które są powiązane z porządkiem mszy świętych. Stąd też pojawiają się tam
|
||||
wyrażenia takiej jak rozkład mszy lub porządek liturgii.
|
||||
|
||||
Wyrażenie regularne \mintinline{text}{bad_regex} ma za zadanie dopasować się do
|
||||
słów, które są powiązane z innymi nabożeństami niż msze święte. Stąd pojawiają
|
||||
się tam wyrażenia takie jak nabożeństwa czerwcowe czy nabożeństwa maryjne.
|
||||
|
||||
\section{Anotator danych}
|
||||
\begin{figure}[tbh!]
|
||||
\center
|
||||
\includegraphics[width=0.6\hsize]{annotator.png}
|
||||
\label{annotator_pic}
|
||||
\label{anotator_pic}
|
||||
\end{figure}
|
||||
System crowdsourcingowy został stworzony w celu zebrania jak największej ilości
|
||||
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.
|
||||
rozpoczęcia mszy świętej, czy nie.
|
||||
|
||||
Do dokończenia
|
||||
|
||||
@ -410,9 +705,6 @@ Do napisania
|
||||
Do napisania
|
||||
% \section{Organizacja danych} % może zbyt inżynierskieby
|
||||
|
||||
\chapter{Perspektywy na przyszłość}
|
||||
Do napisania
|
||||
|
||||
\chapter{Podsumowanie}
|
||||
Do napisania
|
||||
|
||||
|