I’m trying to extract some data for a little research project in real estate economics and would like to get the price, the lot area, the description, the location, etc., out of <script type="application/ld+json">. I know I can use CSS Selectors on this site. However, Hemnet aggregates offers from several websites and CSS Selectors differ depending on the site the offer comes from. I wuld thus like to know how to get data from <script type="application/ld+json"> because it might also be useful later.
I have already tried this :
library(rvest)
library(xml2)
library(jsonlite)
library(dplyr)
o_url <- "https://www.hemnet.se/bostad/tomt-lisselbo-falu-kommun-svartskar-1-17-14704536"
o_html <- read_html(o_url)
o_json <- html_nodes(o_html, "[type="application/ld+json"]") %>% html_text()
ldjson <- jsonlite::fromJSON(o_json)
However, I’m getting this error message:
Error: parse error: trailing garbage
https://www.hemnet.se" } { "@context": "http://schem
(right here) ------^
I think it might be a format problem but I don’t really know much about json. I’ve only started using APIs recently. Indeed, ‘o_json’ looks like this:
[1] ...
[2] "n {n "@context": "http://schema.org/",n "@type": "Product",n "name": "Svartskär 1:17",n "image": "https://bilder.hemnet.se/images/itemgallery_L/40/dd/40dde2279382da793a435e1d71879ebb.jpg",n "description": "Nu finns möjligheten att förvärva en tomt med sjöläge i Lisselbo! Markarbeten är utförda och kommunalt avlopp är betalt. Kommunalt vatten kostar ca 30000 kronor att koppla in och finns vid tomtgränsen. Varmt välkomna att besöka tomten. Vid frågor kontakta oss.",n "offers": {n "@type": "Offer",n "priceCurrency": "SEK",n "price": 950000,n "priceValidUntil": "2020-09-14T13:32:20+0200",n "availability": "http://schema.org/InStock",n "validFrom": "2018-09-14T13:32:20+0200",n "url": "https://www.hemnet.se/bostad/tomt-lisselbo-falu-kommun-svartskar-1-17-14704536"n },n "mpn": "14704536",n "brand": "SkandiaMäklarna Falun"n }n"
[3]...
I thought there was a problem with "n" and tried this:
library(stringr)
clean_json <- str_remove_all(o_json, "n")
ldjson <- jsonlite::fromJSON(clean_json)
However, I still get the same error message…
Thank you in advance for your help! If you also have any advice on my code (not only about the problem I’ve been facing), I would be happy to hear it!
2
Answers
Ok, my bad. I think I've found a(nother) way to do it. First, you need to:
install.packages(jsonld)
For instance, if you want to get the price, use:
We now get 950000 as numeric! If you find a better way to do it, please tell me
As noted in the comments, the first element returned by the selector in not a valid JSON,
returns:
Though it apparently passes structured data / JSON-LD validation ( https://validator.schema.org/ ), 2nd block is just ignored.
And you probably should not call
jsonlite::fromJSON(o_json)
, that isfromJSON()
on a vector of multiple JSON strings. It’s not vectorized and somewhat surprisingly it does not complain nor use just the first value, but it seems to collapse the argument vector and fails again.Simplified example:
Extracting data from json-ld elements might look something like this:
Created on 2023-07-10 with reprex v2.0.2
Number of json-ld elements do not seem to be limited by 3, some pages included structured text entries for events too, for example.