Andmete automatiseeritud eraldamine veebist
Veebis on aina rohkem andmeid struktureerimata kujul. Näiteks ilmaennustusi, korterite hindu, geograafilist infot, sotsiaalvõrgustike andmeid, valimistulemusi, aktsiahindu või ajalehe artikleid ei ole alati saadaval csv või Exceli failina. Alati on võimalik andmeid manuaalselt kopeerida, aga see on tülikas, aeganõudev ja vigaderohke. Veebilehtedel oleva info automatiseeritud eraldamiseks on suuresti kaks võimalust:
- Rakendusliidesed (web API) - struktureeritud http päringud tagastavad andmed (üldjuhul) JSON või XML formaadis.
Soovides teada saada Suur-Britannia kriminaalse tegevuse statistikat, saame seda küsida UK politsei veebiliidese kaudu. Veebiaardessile https://data.police.uk/api/crimes-street/burglary? sisestada aasta-kuu, laius- ja pikkuskraadid ja saame kätte selle koha statistika varastamise kohta esitatud teatised. Vastavad
library(tidyverse)
library(httr)
library(jsonlite)
path <- "https://data.police.uk/api/crimes-street/burglary?"
paring <- GET(url = path,
query = list(
lat = 53.421813,
lng = -2.330251,
date = "2018-05")
)
vastus <- content(paring, as = "text", encoding = "UTF-8")
Tulemuseks on JSON fail (objekt vastus
), millest tükikene on näidatud järgnevalt (R-is see tekst muidugi nii ilus välja ei näe!):
[{...
# osa teksti on eemaldatud
},
{
"category": "burglary",
"location_type": "Force",
"location": {
"latitude": "53.427603",
"street": {
"id": 718271,
"name": "On or near Priory Road"
},
"longitude": "-2.308988"
},
"context": "",
"outcome_status": {
"category": "Unable to prosecute suspect",
"date": "2018-06"
},
"persistent_id": "97a11bad36eb26b43ecc5b9836cebc08c096215fc82ebd9defdc9840854f0e0d",
"id": 64896273,
"location_subtype": "",
"month": "2018-05"
},
# osa teksti on eemaldatud
]
JSON failist omakorda info kättesaamine käib järgnevalt:
andmed <- fromJSON(vastus, flatten = TRUE) %>%
data.frame()
kable(head(select(andmed, month, location.street.name, outcome_status.category)))
month | location.street.name | outcome_status.category |
---|---|---|
2018-05 | On or near Priory Road | Unable to prosecute suspect |
2018-05 | On or near Beaufort Avenue | Investigation complete; no suspect identified |
2018-05 | On or near Trinity Avenue | Investigation complete; no suspect identified |
2018-05 | On or near Hyde Grove | Investigation complete; no suspect identified |
2018-05 | On or near Fownhope Avenue | Investigation complete; no suspect identified |
2018-05 | On or near Hollins Grove | Investigation complete; no suspect identified |
- Ekraanilt kraapimine - andmete eraldamine veebilehe lähtekoodist.
Praktikumis keskendume sellele, kuidas infot eraldada lähtekoodist.
NB! Mängureeglid:
- Vaata, kas andmed on struktureeritud kujul olemas või on veebilehel olemas API (kui on, siis kasuta neid ja ära kraabi).
- Vaata ja austa veebilehe robots.txt faili (nt ut.ee/robots.txt). See määrab, milliseid kohti veebilehest lubatakse robotil protsessida.
- Kraabi ainult neid andmeid, mida vajad.
- Oota teatud aeg (näiteks 1 sekund) pärast iga uut päringut.
Veebilehtede ülesehitusest
Et tegeleda andmete kraapimisega veebist, on vaja omada ülevaadet süntaksist, millega veebilehti koostatakse. Seega tutvume HTML-i põhitõdedega. Alustame näitest:
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<h1>This is a Heading</h1>
<p>This is a paragraph.</p>
</body>
</html>
Et näha tulemust, võid ülevaloleva koodi salvestada .html failina ning avada brauseris. Alternatiivina kliki siia.
Lühidalt kokku võttes: HTML koosneb siltidest (tags), mis märgitakse sümbolite < > vahele ning mille abil kirjeldatakse veebilehe struktuuri.
Rohkem infot HTML siltide kohta leiad siit.
HTML määrab veebilehe üldise struktuuri. Et muuta teksti värvi ja muud stiili, selleks kasutatakse CSS-i.
Vaata näiteid:
Andmete kättesaamise idee seisnebki selles, et veebilehe lähtekoodist leiame ülesse vajaliku sildi ning eraldame vastava väärtuse. CSS-i määratud klassid ja id-d, aitavad meil tihti hõlpsamini vajaliku info asukohta määrata.
Rohkem infot HTMLi ja CSS kohta leiad:
CSS-i õppimiseks on tore tutorial:
Paketi rvest minimaalne näide
rvest on Hadley tehtud pakett veebilehtedelt andmete kraapimiseks.
HTML
Minimaalne näide, kuidas eelneval pildil näidatud HTML lähtekoodist eraldada pealkirja ja lõiku.
library(rvest)
html_source = '
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<h1>This is a Heading</h1>
<p>This is a paragraph.</p>
</body>
</html>
'
page = read_html(html_source)
# pealkirja eraldamine
page %>%
html_node("h1") %>%
html_text()
## [1] "This is a Heading"
# lõigu eraldamine
page %>%
html_node("p") %>%
html_text()
## [1] "This is a paragraph."
Funktsioonile read_html
võib ette anda kas veebilehe urli, faili asukoha või sõne.
XML
XML on märgistuskeel, mille eesmärgiks on struktureeritud info jagamine. XML koosneb kasutaja defineeritud siltidest (tags), mis märgitakse sümbolite < > vahele ja mille abil kirjeldatakse andmete struktuuri. Järgnevalt on toodud minimalistlik näide, kuidas XML failist eraldada infot.
library(rvest)
xml_source = '
<?xml version="1.0" encoding="UTF-8"?>
<inimesed>
<inimene>
<nimi>Mati</nimi>
<vanus>25</vanus>
</inimene>
<inimene>
<nimi>Kati</nimi>
<vanus>40</vanus>
</inimene>
</inimesed>
'
page = read_html(xml_source)
# vanuste eraldamine
page %>%
html_nodes("inimene") %>%
html_node("vanus") %>%
html_text()
## [1] "25" "40"
Funktsiooni read_html
asemel võib kasutada funktsiooni read_xml
või html_node
asemel xml_node
, kuid vastavad XML-ekvivalendid kutsuvad välja vastavad html funktsioonid, seega ei ole tegelikult vahet, kumba varianti kasutada.
Uuri ka rvest dokumentatsiooni.