Od wersji 1.56 boost, posiada fajną bibliotekę, dostarczająca informacje o typie zmiennej (boost_typeindex). Podobno radzi sobie lepiej, niż mechanizmy typeid() albo std::type_index (C++11). Z pewnością wyniki są bardziej czytelne dla człowieka.
W Ubuntu 14.10 dostępny jest tylko boost w wersji 1.55, więc trzeba ściągnąć źródła samodzielnie:
wget -c http://sourceforge.net/projects/boost/files/boost/1.57.0/boost_1_57_0.tar.gz/download
mv download boost_1_57.tar.gz
tar -zxv boost_1_57.tar.gz
Podczas kompilacji trzeba jeszcze wskazać gdzie są nasze pliki nagłówkowe:
Rozwiązanie problemu archiwizacji strony, do której konieczne jest logowanie. Po zalogowaniu tworzona jest sesja, którą można wykorzystać do ściągnięcia zawartości strony:
wget --save-cookies cookies.txt \ # zapisuje ciasteczko
--keep-session-cookies \ # ciasteczka sesji normalnie nie są zapisywane, ta opcja to wymusza
--post-data 'user=Alice&pass=123' \ # logowanie na stronie (metoda POST)
http://example.com
wget --recursive \ # przeszukaj stronę rekursywnie
--cookies=on \ # man nie opisuje, wget nie odrzuca, niektóre przykłady podają (?)
--load-cookies cookies.txt \ # ładuje wcześniej zapisane cookie
--keep-session-cookies \ # nadal utrzymuje cookie sesji
--no-clobber \ # nie nadpisuj już istniejących plików
--page-requisites \ # ściągnij wszystkie pliki (pliki dźwiękowe, css, itd.)
--html-extension \ # zapisz pliki z rozszerzeniem html
--restrict-file-names=windows \ # eskejpuje znaki by Windows (są też inne tryby) sobie poradził
--domains example.com \ # nie śledź linków poza domenom
http://example.com
Podzieliłem problem na dwie części, ale pewnie da się to zamknąć do jednego polecenia.
Czasami zachodzi potrzeba, przeanalizowania danych, na które nie ma dedykowanego parsera. Niekiedy wystarcza regexp, ale jeżeli struktury danych zaczynają być zagnieżdżone, można pokusić się o stworzenie gramatyki i skorzystanie z jakiejś biblioteki. Ponieważ dawno się już tym nie zajmowałem, nie przywiązywałem szczególnej uwagi, czy biblioteka pozwala na zapis zbliżony do notacji BNF (http://pl.wikipedia.org/wiki/Notacja_BNF).
Do budowania gramatyk, najlepiej korzystać z operatorów +, ^, |. Do dopasowania tekstu służy nam wiele obiektów (tokenów) np.
Word - dopasowuje tekst z dowolnego złożenia znaków
Literal - dopasowuje zwartość do znaków dokładnie w takiej kolejności jak zostały podane
Suppress - dopasowuje, ale zawartość zostanie pominięta w wyniku
Problemem może być dopasowywanie do zagnieżdżonych zawartości. Token w takim przypadku, powinien odwoływać się sam do siebie. Z pomocą przychodzi Forward(), a ostateczny opis należy wykonać za pomocą operatora << (linijka 14). Group, pozwala na grupowanie wyników/tokenów jakie pojawią się w ostatecznym wyniku.
Słowo jeszcze o metodach, które okazały się w moim przypadku niezwykle przydane:
delimitedList(expression, delim=',') - dopasuje wyrażenie, rozdzielone za pomocą delimitera (domyślnie jest to przecinek)
Group.setResultsName() - nadaje nazwę do dopasowanego tokenu, ma niby posłużyć w celu zbudowania słownika ze sparsowanymi danymi, ale ja po prostu korzystam z getName() na wynikowych danych, gdy po nich iteruje
ParseResults.asList() - wynik domyślnie jest obiektem ParseResult, ale możemy skorzystać z konwersji i przekształcić go na listę