R, rvest i web-harvesting



Źródło flickr

Wyciąganie danych z treści stron internetowych to źródło interesujących informacji. Kiedyś wymagało to sporo samozaparcia i pokracznych skryptów w Perlu walczących z bałaganiarskimi źródłami stron internetowych. Dzisiejsze strony internetowe coraz częściej są zgodne ze standardami, jest też coraz więcej cywilizowanych narzędzi do ich parsowania.

Ostatnio moją olbrzymią sympatię zyskał pakiet rvest pozwalający na bardzo proste wyłuskiwanie danych ze stron. Przedstawię go na przykładzie pobierania ocen odcinków seriali telewizyjnych w zależności od wieku i płci oceniającego. Za tydzień zrobimy użytek z tych danych, ale dzisiaj skupimy się na tym jak te dane pobrać.

W serwisie Internet Movie DataBase (IMDB) na stronach “user ratings” (np. tutaj) znajdują się oceny filmu w rozbiciu na grupy wiekowe i płeć.

Z użyciem pakietu rvest pobranie danych i parsowanie strony html do drzewa html sprowadza się do dwóch linii.

Z tego drzewa html możemy wybrać interesujące nas elementy / węzły. Aby określić, które węzły nas interesują, użyjemy genialnego narzędzia SelectorGadget (http://selectorgadget.com/). Z jego pomocą wybór interesujących nas elementów sprowadza się do wyklikania na stronie treści, które chcielibyśmy odczytać oraz tych których odczytać nie chcemy. SelectorGadget zaproponuje tzw. Css selector i na żółto pokaże, jakie elementy strony pasują do niego. W przypadku naszych filmów poszukiwany selector to "table:nth-child(11) td:nth-child(3)".


Zdjęcie strony internetowej z zaznaczonymi elementami przez SelectorGadget. Na żółto zaznaczone są elementy pasujące do wzorca. Na czerwono i zielono zaznaczono węzły uczące.

Aby więc wyłuskać interesujące nas dane, musimy
1. wybrać węzły drzewa html pasujące do selektora (funkcją html_nodes)
2. wyciągnąć z tych węzłów tekst (funkcją html_text), gdyby poza liczbami było w tym tekście coś jeszcze, to możemy go oczyścić wyrażeniem regularnym.

Poniższe trzy linie jako wynik zwrócą oceny różnych grup wiekowych i płci dla określonego filmu (w tym przypadku BreakingBad).

Banalne!

Powtórzmy to teraz dla wszystkich seriali. Zobaczymy, które są preferowane bardziej przez kobiety a które przez mężczyzn. Które zyskują uznanie u młodszych odbiorców a które u starszych.

Adresy stron internetowych w serwisie IMDB zamiast tytułu serialu wykorzystują identyfikator wyglądający dla serialu BreakingBad tak: tt0903747.

Skąd brać te identyfikatory dla interesujących nas filmów? Wykorzystamy zbiór danych serialeIMDB z pakietu PogromcyDanych. W kolumnie imdbId, przedstawione są identyfikatory ponad 200 najpopularniejszych seriali.

Poniższy kod dla każdego serialu pobierze stronę z ocenami serialu, pobierze oceny w rozbiciu na płeć i wiek oraz zapisze je do tabeli ratings.

Poniżej przedstawiamy 10 pierwszych wierszy oraz wybrane cztery kolumny z pobranego zbioru danych.


> ratingsGroup[1:10, c(1,2,6,12)]
Males Females Aged 18-29 Aged 45+
tt0903747 "9.6" "9.3" "9.6" "9.3"
tt2395695 "9.4" "9.5" "9.5" "9.1"
tt0795176 "9.5" "9.5" "9.5" "9.4"
tt0944947 "9.5" "9.4" "9.6" "9.2"
tt2356777 "9.3" "9.1" "9.4" "9.0"
tt0306414 "9.5" "8.6" "9.4" "9.1"
tt1475582 "9.2" "9.4" "9.4" "9.0"
tt0081846 "9.4" "9.2" "9.2" "9.4"
tt0141842 "9.3" "9.0" "9.4" "9.1"
tt1831164 "9.1" "9.3" "9.4" "7.1"

Za tydzień pokażemy aplikacje pokazującą różnice w ocenach pomiędzy mężczyznami a kobietami.


Wpisy z kategorii Duże i złożone powstają przy współpracy z firmą CodiLime.

4 myśli na temat “R, rvest i web-harvesting”

  1. @Marcin,
    dzięki za literówkę,

    co do xpath, to wystarczy użyć argumentu xpath zamiast css
    http://xkcd.com/293/

    html_nodes(ht, xpath = “//table[(((count(preceding-sibling::*) + 1) = 11) and parent::*)]//td[(((count(preceding-sibling::*) + 1) = 3) and parent::*)]”)

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

Możesz użyć następujących tagów oraz atrybutów HTML-a: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">