Poprzedni post, “Podsumowanie Microsoft Ignite 2017 – analiza wydarzenia na Twitterze z wykorzystaniem Power BI”, pokazywał konkretny przykład analizy wybranego hashtagu w Power BI. Mimo, że Power BI wspiera naprawdę dużo źródeł danych, nie ma niestety bezpośredniego połczenia do portalu Twitter. Owszem, można skorzystać z oficjalnego API dostarczanego przez Twitter i wykorzystać, nawet bezpośrednio, z poziomu Power BI, natomiast problemem mogą okazać się limity. Dość skomplikowanym etapem jest również przygotowanie danych do analizy. Tutaj również, mimo, iż Power BI dostarcza ogromna ilość transformacji, w przypadku analizy tekstu wymaga to naprawdę sporo pracy i jest stosunkowo wolne.
Przykład analizy tekstu w Power BI prezentowałem w jednym z wcześniejszych postów: https://pl.seequality.net/power-query-tutorial-cz-2/ Jak widać, żeby efektywnie analizować tekst, w tym przypadku wpisy z Twittera, najlepszym rozwiązaniem wydaje się przygotowanie dodatkowych mechanizmów, które przygotują dane do analizy. W tym wpisie pokażę przykład zrobiony z wykorzystaniem języka C# i bazy danych SQL Server. Zaprezentuje szczegóły techniczne, pokażę fragmenty kodu i podam link do całego repozytorium, który będziecie mogli przetestować sami. Zapraszam.
Cel
Tylko w kwestii przypomnienia chciałbym krótko opisać cel, który chciałem osiągnąć. Mianowicie, moim celem była analiza wybranego hashtagu na Twitterze. Do takiej analizy potrzebne mi były zatem wpisy z Twittera z konkretnego hashtagu. Następnie dane te (wpisy) musiały zostać odpowiednio przygotowane i zapisane w bazie danych oraz na samym końcu należało oczywiście przygotować raporty i analizy. Te właśnie procesy opiszę w tym poście.
Pobieranie danych
Idea
Istnieje wiele metod, które pozwalają na pobieranie danych z Twittera. Przykładem może być oczywiście API, ale dostępne są również serwisy, które pobierają dane za nas i udostępniają je do analizy. Niestety rozwiązania te nie są idealne, a już szczególnie, gdy potrzebujemy takie dane pobrać szybko lub jednorazowo. API może w takim przypadku się nie sprawdzić ze względu na limity, natomiast za dodatkowe serwisy należy zapłacić i często nie oferują one danych historycznych. Na potrzeby mojego pomysłu, czyli analizy stosunkowo mało popularnego hashtagu, wybrałem metodę półautomatyczną, którą “wymyśliłem” sam.
Korzystając z API Twittera musimy zmierzyć się z limitami, natomiast przeglądając Twittera w przeglądarce takie limity nas nie dotyczą. Jako że przeglądając Twittera widzimy wpisy, czyli interesujące nas dane, są one również dostępne w kodzie źródłowym, który można podglądnąć w przeglądarce. Idea pobierania danych była zatem bardzo prosta:
- przejdź do tablicy wybranego hashtagu na Twitterze
- przewiń wszystkie wpisy do końca
- podejrzyj kod źródłowy i zapisz do pliku
Wykonanie
Niestety podczas próby wyświetlenia kodu źródłowego strony zdarzało się, że przeglądarka Google Chrome się zawieszała i dlatego też, musiałem wykorzystać wyszukiwarkę na Twitterze. Za pomocą odpowiednich parametrów możemy zdefiniować “zapytanie”, które następnie możemy wkleić do wyszukiwarki lub skorzystać z funkcjonalności “Advenced search”, która to zapytania wygeneruje za nas.
Zostanie to przetłumaczone do następującego adresu:
https://twitter.com/search?f=tweets&vertical=default&q=%23msignite%20since%3A2017-09-18%20until%3A2017-09-19&src=typd
Dzięki temu możemy zawęzić pobieranie danych do jednego dnia, a nawet do wpisów zawierających poszczególne słowa lub hashtagi. W moim przypadku Chrome miał problemy z zapisaniem pojedynczego dnia, więc musiałem jeszcze bardziej zawęzić filtr. W tym celu udałem się na jedną ze stron, która pokazuje wstępną analizę dla podanego przez nas hashtaga. Ze strony tej odczytałem najpopularniejsze tagi, które są dodawane do wybranego przeze mnie tagu. Następnie w sytuacji, gdy nie mogłem zapisać wszystkich wpisów z całego dnia, najpierw pobierałem wpisy dla wybranych najpopularniejszych tagów, które występowały razem z badanym i potem pobierałem resztę tweetów. W ten sposób byłem w stosunkowo krótkim czasie zapisać całą historię wybranego hashtagu w kilkunastu plikach txt z kodem HTML.
Warto również dodać, że istnieją wtyczki do przeglądarek, które mogą nam pomóc “przewijać” stronę, dzięki czemu nie musimy marnować czasu na ręczne przewijanie. Przykładem może być dodatek “Simple Autoscroll” do przeglądarki Google Chrome. Oczywiście metoda ta zadziała nie tylko na Twitterze, ale również dowolnej stronie. Ponieważ web scrapping nie jest zbyt dobrze zdefiniowany w prawie oraz, że tak naprawdę wszystko zależy od polityki prywatności oraz regulaminu strony WWW przed pobieraniem zalecam zapoznać się tymi dwiema kwestiami. Nie zalecam również wykorzystywać tej metody do analizy popularnych hashtagów lub nieustannego pobierania danych ze stron.
Przygotowanie danych do analizy
Parsowanie danych
Pobrane dane miały format kilkunastu plików HTML zapisanych na lokalnym dysku twardym. Niestety parsowanie plików HTML nie jest rzeczą trywialną i w samym Power BI, czyli narzędziu, w którym chciałem przygotować analizy, byłoby to niewykonalne, musiałem przygotować niewielką aplikację, która pomogła mi przeczytać zapisane pliki i zapisać dane do bazy. W tym celu wykorzystałem mój ulubiony pakiet HTMLAgilityPack (https://www.nuget.org/packages/HtmlAgilityPack/), który służy właśnie do parsowania HTML. Przykładowa metoda do odczytywania danych wyglądała następująco:
var tweets = fileContent.HTMLDocument.SelectNodes("//div[@class='content']"); foreach (var tweet in tweets) { Tweet currentTweet = new Tweet(); int iNumberOfErrorsDuringParsing = 0; try { currentTweet.UserAddressName = tweet .SelectSingleNode(".//div[@class='stream-item-header']//a[@class='account-group js-account-group js-action-profile js-user-profile-link js-nav']") .GetAttributeValue("href", String.Empty) .ToString() .Trim(); } catch (Exception exc) { iNumberOfErrorsDuringParsing++; logger.Error("Error during parsing " + "UserAddressName" + " " + exc); } }
Zasada działania wcześniej wspomnianej biblioteki jest bardzo prosta i opiera się na wykorzystaniu odpowiednich ścieżek “XPATH” oraz operacji na kolekcjach i obiektach do odczytania odpowiedniego tekstu lub atrybutu znaczników HTML. Wykorzystując projekt biblioteki i aplikacji konsolowej oraz języka C# przygotowałem parser, który potrafi odczytać dane z kodu Twiettera oraz zapisać do bazy danych. Dodam tylko, że w aplikacji nie korzystałem z ORM, natomiast wykorzystałem procedury składowane do wprowadzania danych. Przykładowo:
foreach (var result in textMiningResults) { cmd = new SqlCommand("[Internal].[sp_InsertToken2Gram]", conn); cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.Add("@TweetID", SqlDbType.Int).Value = result.TweetID; cmd.Parameters.Add("@Token", SqlDbType.NVarChar, 500).Value = result.Token; try { cmd.ExecuteNonQuery(); } catch (Exception exc) { logger.Error(exc); } }
Przygotowanie danych do analizy
Dane przed analizą musiały zostać jeszcze dodatkowo przygotowane. W tym celu w klasie TextMining zostało zdefiniowanych kilka metod, które umożliwiają:
- MineEntireTweetTextsAndSaveIntoDatabase – ogólne czyszczenie tekstu wpisu
- MineTweetHashtagAndSaveIntoDatabase – ekstrakcja tagów z wpisu
- MineTweetAccountsAndSaveIntoDatabase – ekstrakcja kont użytkowników z wpisu
- MineTokenizeTweet1Gram – podział tekstu na n-gramy (tokeny), metody dla analizy 1-gram, 2-gram oraz 3-gram
- tmRemoveSpecialCharactersFromWord – usuwanie znaków specjalnych z tekstu
- tmRemoveSpecialCharactersFromText – wstępne przygotowanie tekstu do dalszego czyszczenia znaków specjalnych, obsługa adresów WWW oraz adresów innych mediów
- tmRemoveNonEnglishWords – usunięcie z tekstu słów, które nie występują w angielskim słowniku
- tmRemoveEnglishStopWords – usunięcie z tekstu angielskich “stop words”
- tmCheckIfNumber – sprawdzenie, czy dany wyraz jest liczbą całkowitą lub zmiennoprzecinkową
Baza danych
Sama baza danych została zapisana jako “Database Project” i znajdują się w niej następujące schematy i obiekty (lista niepełna):
- Internal – można powiedzieć schemat dla “stage”, czyli surowe dane pochodzące bezpośrednio z plików. Tabela z tweetami, czyli “Tweet”, tabela “FileContent”, która zawiera kopię tekstu z pliku oraz tabela z logami “Executions”. W tym schemacie zdefiniowane również zostały procedury, które wykorzystane zostały w aplikacji i bibliotece do zapisywania danych i logów.
- Text Mining – schemat, który przechowuje tabele z wynikami działania właściwej części aplikacji. Znajdują się tutaj odpowiednio przygotowane do analizy dane dla Tweetów, Hashtagów, kont użytkowników oraz wyniki analizy tokenów.
- Reporting – schemat zawierający widoki, które służą jako warstwa dostępu do danych dla użytkowników lub narzędzia raportowego
- Analytics – schemat zawierający widoki dla gotowych analiz
Analiza danych i podsumowanie
Raporty oraz właściwa analiza danych została przygotowana w Power BI i można ją zobaczyć w podanym na początku wpisu poście. Jak widać, praktycznie wszędzie można znaleźć ciekawe dane do analizy. Oczywiście czasami ich zdobycie nie jest proste i należy napisać kilka linijek własnego kodu, natomiast suma sumarum nawet z wykorzystaniem półautomatycznego pobierania i przygotowania takich danych w stosunkowo krótkim okresie można osiągnąć ciekawe rezultaty oraz mieć możliwość analizowania realnych danych. Jeżeli jesteście zainteresowani powtórzeniem analizy kod biblioteki, aplikacji oraz raportu dostępny jest na github pod adresem: https://github.com/seequality/seequality_twitter_analysis
- Docker dla amatora danych – Tworzenie środowiska (VM) w Azure i VirtualBox (skrypt) - April 20, 2020
- Power-up your BI project with PowerApps – materiały - February 5, 2020
- Docker dla “amatora” danych – kod źródłowy do prezentacji - November 18, 2019
Last comments