Textová analýza recenzí brněnských restaurací

Závěrečný projekt XI. Digitální akademie: Data v Brně

Alena Frydrychová & Andrea Waltlová

Jak to všechno začalo

S Andy jsme spolužačky ze školy, ale že se obě hlásíme do akademie jsme zjistily, až když jsme byly přijaté. Více jsme se sblížily na samotné akademii a protože jsme si sedly, rozhodly jsme se udělat společně i projekt. Obě jsme už měly zkušenost s SQL a Power BI ze školy, ale nadchlo nás programování v Pythonu, a tak jsme se rozhodly na něj v projektu zaměřit.

Něco o nás

Obě studujeme na Filozofické fakultě Masarykovy univerzity magisterský obor Informační studia se zaměřením na informační a datový management. Andy tento obor studovala i na bakaláři, zatímco já jsem udělala obrat o 180° a na Informační studia jsem přešla z francouzské a polské filologie. Do digitální akademie jsme se přihlásily, protože nám datové předměty ve škole nestačí, chtěly jsme prostě vědět víc! :)

První nápady

Po představení dat, byla naším prvním nápadem (říkejme mu plán A) Analýza vlivu konaných událostí v Brně na vytížení MHD. Cílem mělo být lepší plánování kapacity spojů a posil. Nápad to byl sice super, ale když jsme dostaly reálná data (která jsme měly k dispozici vpodstatě až několik dní před hackathonem), zjistily jsme, že s nimi projekt nebude možné realizovat kvůli nízké granularitě. Narychlo jsme tedy vymýšlely plán B. Andy dostala nápad, že bychom místo čísel mohly analyzovat text! V akademii všechny týmy pracovaly s čísly, a tak nápad věnovat celý projekt textu, místo číslům, byl unikátní.

Cílem plánu B tedy bylo udělat textovou analýzu recenzí brněnských památek a parků na portále tripadvisor. Recenze byly navíc dostupné i v angličtině, díky tomu nás poprvé napadla i analýza sentimentu. S tímto nápadem jsme šly na hackathon.

Hackathon

Plánu B jsme obětovaly většinu dvanáctihodinového hackathonu, ale bohužel jsme zase narazily na potíže. API tripadvisoru nebyla dostupná, a i když jsme se dlouho snažily scrapovat data pomocí Pythonu a nějakým způsobem obejít zabezpečení stránky, stejně nám byl přístup odepřen.

Svého plánu jsme se ale vzdát nechtěly. Nápad se nám moc líbil a byl realizovatelný, i když jsme s Pythonem teprve začínaly. Řekly jsme si tedy, že aplikujeme stejný postup jen na jinou stránku. Tentokrát jsme na radu Honzy Dupala zkusily štěstí na webu Foursquare, který má dostupné API. Po docela zdlouhavé registraci (během čehož jsme se snažily vyhnout zadávání kreditní karty) a následném čtení dokumentace, se nám úspěšně začaly vracet JSON záznamy s prvními recenzemi. Jakkoli nadějně to už vypadalo, opět jsme pohořely. API bylo sice dostupné, ale jen omezeně. Pro každé místo v Brně bychom dostaly jen jednu recenzi, což by nebylo moc vypovídající. Tím tedy plán B skončil.

V této fázi přišla asi největší zoufalost. Blížil se konec hackathonu a my stále neměly žádná data, která bychom mohly začít zpracovávat. V ten moment zakročil náš mentor Martin, který s námi celým procesem prošel a poradil nám najít si opravdu jednoduchou statickou stránku, z které nebude takový problém recenze stáhnout. A my ji našly!

Definitivní projekt

Nakonec jsme tedy zvolily jednoduchý web fajnsmekr.cz. Po vyhledání Brna je k nalezení 800 různých zařízení (pizzerie, vinárny, pivnice, restaurace…) a každé toto zařízení má vlastní profil s recenzemi.

Záměrem našeho projektu je v první řadě procvičit si to, co jsme se naučily na akademii a především se zaměřit na programování v Pythonu. Zároveň nás zajímá zpracování přirozeného českého jazyka, který se potýká s více problémy, než například angličtina.

Před samotnou analýzou jsme si stanovily několik hypotéz:

  • Lidé píší spíše negativní hodnocení
  • Negativní recenze bývají delší
  • Mezi nejčastější slova bude patřit jídlo, pití, obsluha a prostory
  • Nejvíce recenzované budou restaurace v centru

Využití projektu

Projekt může sloužit jako podklad pro tvorbu nástroje textové a obsahové analýzy a analýzy sentimentu, přičemž vstupem může být jakýkoliv text. Taková analýza může vést ke zlepšování služeb nebo k odhalování skrytých vazeb a korelací v textových datech.

Web scraping

Celé šťastné jsme se pustily do scrapingu recenzí brněnských restaurací. Vzhledem k tomu, že už jsme měly za sebou několik neúspěšných pokusů, vše jsme docela snadno a rychle v Pythonu naprogramovaly. S přístupem problém nebyl, ale za to nás potrápila stará tabulková šablona stránky, kde měly značky <div> stejné classy v různých částech stránky a chvilku nám trvalo najít tu správnou cestu.

V této fázi jsme programovaly jak divé (a do konce projektu jsme vlastně programovat nepřestaly) a využívaly jsme knihoven BeautifulSoup a lxml. Hodně nám pomohly také regexy a Xpath. Když jsme k recenzím konečně našly správnou cestu, začaly jsme je zapisovat do souboru csv. Jen pro zajímavost, návštěvnost stránky, z které jsme stahovaly recenze, jsme opakovanými requesty zvedly asi o třicet tisíc, takže jsme stránku tak trochu probudily z mrtvých. :)

Čištění dat

Když už jsme měly postahované všechny recenze a přiřazené, ke kterým restauracím patří, přišlo na řadu čištění dat. Nejvíce jsme musely zapracovat na opravě kódování, k čemuž jsme využily Excel, a také na odstranění stop slov, tzn. spojek, předložek a podobně, aby nám k samotné analýze zbyly jen čisté recenze s významovými slovy. Dále jsme k textové analýze používaly převážně knihovnu NLTK. Knihovna umožňuje zvolit si defaultní stopslova, akorát ne pro češtinu, proto jsme si udělaly vlastní seznamy stopslov. Mezi stopslova jsme zařadily spojky, předložky, modální slovesa a zájmena. Také jsme vyřadily slova “jídlo”, ”obsluha” a “restaurace”, která se v recenzích vyskytují opakovaně a ve vizualizacích nemají vypovídající hodnotu.

Textová analýza a lemmatizace slov

Teď bychom se už konečně mohly dostat k samotné textové analýze, co?

I když se na první pohled nezdá, textová analýza byla docela výzva. Určit nejčastější slova nebyl takový problém. Ten nastal až když jsme zjistily, že se nám v nejčastějších výskytech objevuje více tvarů jednoho slova. Rozhodly jsme se proto všechny slova v recenzích lemmatizovat, tzn. převést do základního tvaru. Nad správným přístupem jsme chvíli uvažovaly, až jsme našly API od FI MUNI, které dokáže lemmatizovat český text. Využívaly jsme k tomu Python a výsledky opět zapisovaly do CSV. Práci s API už jsme měly nacvičenou a jelikož výstupem API byl JSON, bylo jednoduché zapsat odpovědi do csv. Některé recenze jsme také musely rozdělit na části, protože maximální délka posílaného textu nesměla přesáhnout 1000 znaků. Opět jsme si tedy pohrály v Pythonu s listy a delší recenze splitnuly a přidělily jim správná id recenzí, abychom je následně mohly zase spojit. Ke spojení jsme využili Excel a dostupné rozšíření Kutools, které umožňuje spojit řádky na základě hodnoty v daném sloupci — u nás tedy hodnota review_id. Co nás trochu zdrželo v získání všech lemmatizovaných recenzí, byl limit API na 500 requestů za den.

Andy se s Pythonem rozhodla potrápit ještě víc a výsledek vizualizovala nejčastější slova pomocí knihovny wordcloud a vizualizaci doplnila také o frekvenci slov v tabulkách, které vytvořila pomocí knihovny Pandas. Wordcloudy jsou o tabulky doplněné z důvodu zobrazení přesných výsledků, jelikož vizualizace v Pythonu nejsou interaktivní.

Sentiment analysis

Možná si říkáte, proč máme wordcloudy rovnou dva. Totiž, zatímco si Andy hrála s lemmatizací, já jsem zapracovala na analýze sentimentu. Protože analýza sentimentu skýtá v češtině mnohá úskalí a je potřeba dávat si pozor na užití slov v jiném významu, ironii a sarkasmus atp., jako nejschůdnější řešení jsme zvolily využít API Geneea, což je aplikace pro analýzu sentimentu češtiny. I když jsme práci s knihovnou requests a s využitím API měly už docela nacvičenou, stejně jsme narazily na menší problém. Limit pro stahování dat byl nastaven na 5 MB, což jsme velmi rychle vyčerpaly. Když jsem poté zvládla vyčerpat i limit účtu našeho lektora, kontaktoval mě majitel stránky a zjišťoval o našem projektu více podrobností. Měly jsme ale to štěstí, že pan majitel byl moc milý a limit účtu nám bez problému zvýšil. Při tomto problému jsme si tedy vyzkoušely nejen programovací schopnosti, ale i ty komunikační. :)

Takto jsme tedy určily sentiment každé recenze a rovnou k tomu přidaly i počet znaků v každé, pro pozdější zkoumání korelace mezi délkou recenze a jejím sentimentem. Tuto korelaci jsme vytvořili opět v Pythonu za pomocí knihoven numpy, matplotlib a pandas.

Slušnost negativních recenzí

API na FI MU nabízí službu, která zadaný text označí jednou ze tří úrovní: polite, rude, very rude a vypíše všechny neslušná slova, která v textu objeví. Řekly jsme si proto, že by bylo hezké ověřit slušnost recenzí a zjistit, zda uživatelé používají v negativních recenzích i sprostá slova, případně jaká. Byly jsme zvědavé, jaká slova toto API vyhodnotí jako neslušná. Výsledná slova si můžete prohlédnou v reportu z Power BI níže.

Word frequency & concordance

Nakonec zbývalo jen určit kontext, v kterém se nejčastěji vyskytující se slova (tedy restaurace, jídlo a obsluha) nachází. Na to jsem opět využila starých dobrých listů a v recenzích hledala útržky textu obsahující klíčová slova. Slova vyskytující se v těchto útržcích jsem po lemmatizaci zapisovala do slovníku a počítala jejich četnost. Stopslova jsou opět vyřazená. Výsledky si navíc můžete vyfiltrovat podle negativních nebo pozitivních recenzí.

Andy na to šla jinak a využila funkci concordance z knihovny NLTK, která najde všechny výskyty daného slova a jejich kontext — tedy kousek textu před a za daným slovem.

To, co jsme už nestihly vizualizovat v Pythonu Andy dodělala v Power BI a vytvořila krásný report. Na druhé straně reportu je k dispozici přehled nejfrekventovanějších slov před a za těmi klíčovými.

Podařilo se nám vytvořit i mapu všech restaurací, z kterých jsme recenze použily. Barevně jsou rozlišené podle jejich typu. Adresy jsme opět získaly z webových stránek pomocí Pythonu, a poté jsme pomocí knihovny geopy dohledaly k adresám latitude a longitude, ze kterých jsme v Power BI vytvořily mapu.

Celý report najdete ZDE.

Spolupráce

Po celou dobu projektu jsme spolupracovaly skrze Github, kde jsme si vytvořily repozitář, a ten si poté naklonovaly každá k sobě. Chvíli nám trvalo, než jsme se domluvily s Gitem, ale nakonec jsme se to každá naučila po svém a vše skvěle fungovalo. Andy používá editor Atom, který lze s Gitem i Githubem snadno propojit + Githubovou desktopovou aplikaci pro pushovaní změn do vzdáleného repozitáře. Tato aplikace se mnou ale nechtěla spolupracovat, a tak jsem používala webovou verzi Githubu a příkazovou řádku, do které jsem přímo psala příkazy v Gitu. Práci s Gitem také vnímáme jako další velké plus našeho projektu a skvělou užitečnou znalost.

Celý kód je k dispozici v repozitáři projektu.

Statistické okénko projektu

Počet řádků kódu v použitých skriptech: 628

Počet restaurací: 800

Počet stažených recenzí: 5338

Počet commitů na Githubu: 110

Počet hodin strávených na projektu: 100h +

Počet získaných zkušeností: nevyčíslitelně mnoho