Я (от начинающего до среднего пользователя R) пытаюсь найти в Интернете данные о большом количестве (~ 12 тыс.) Зданий в Берлине.
Информацию можно найти на веб-страницах ( по одной для каждой здание , итого 12k) агентства наследия Берлина, которые все выглядят как это (веб-сайт на немецком языке, данные, которые меня интересуют, - это таблица в центре, которая начинается с Obj .-Dok-Nr .: 09XXXXXXX и следующие строки, содержащие пригород, адрес et c.).
Все URL-адреса заканчиваются на obj_dok_nr=09xxxxxx (09097890-09010001)
, что соответствует внутреннему идентификатору здания. , каждое поле таблицы имеет следующий селектор css:
.denkmal_detail_head+ .denkmal_detail_body tr:nth-child(n) td+ td
, где n является целым числом, начиная с 1.
У меня уже есть все идентификаторы 09XXXXXXX в отдельных фрейм данных denkmal_df , который я построил из файла json, который я нашел в другом месте.
Я написал этот код для извлечения данных:
get_URL <- function(key) { #assemble an URL from a denkmal key
url <- paste0("https://www.stadtentwicklung.berlin.de/denkmal/liste_karte_datenbank/de/denkmaldatenbank/daobj.php?obj_dok_nr=", key)
return(url)
}
get_Data <- function(url, i, static_css_1, static_css_2) { #Webscraper core, needs to be more flexible, but gets the job done
css_key <- paste0(static_css_1,i,static_css_2)#Assemble css key to extract information
print(css_key)
data <- url %>% read_html() %>% html_nodes(css = css_key ) %>% html_text() #extract information
return(data)
}
web_data <- matrix(as.character(NA), nrow = 13, ncol = 13) %>% data.frame() #%>% as_tibble() # prepare Dataframe, faster than creating it in the loop # Why can't I create the tibble directly? matrix(NA, nrow = length(denkmal_df$key), ncol = 13) %>% tibble results in a tibble with one column
temp_data <- NA
css1 <- ".denkmal_detail_head tr:nth-child(" #define css structure # possible improvement: more flexibility
css2 <- ") td+ td"
for(key in 1:length(denkmal_df$keys)){ #loop over all the denkmal keys, using an index called key
i <- 1
temp_data <- NA
url <- get_URL(denkmal_df$keys[key]) #retrieve the url by passing the actual denkmal key to the get_URL function
print(url)
while (is_empty(temp_data) == F){ #start scraping the website belonging to the current denkmal, until no information can be found (temp_data = empty)
temp_data <- get_Data(url, i, css1, css2) #retrieve the first category of data, which is indexed on the website by a css path + a number (1 for the first item, 2 for the second...) -> i
if (i >= ncol(web_data) & is_empty(temp_data) == F) { #check if all columns in the data frame are full, but we still got data from a new category
web_data[key, i+1:i+5] <- as.character(NA) #expand dataframe with a bunch of NA columns
}
if (is_empty(temp_data) == T) {#writing empty values into a dataframe throws an error, so we convert to NA
temp_data <- as.character(NA)
web_data[key, i] <- temp_data
temp_data <- character(0) # and back to empty, to exit the while loop
}
else {
web_data[key, i] <- temp_data # write data to the data frame in row = key(corresponds to postion of the actual key), column = i (represents the category)
i <- i+1 # increase i to extract the second/etc category, rinse and repeat until no categories are left (temp_data = empty)
}
}
}
Пока он очищает данные в порядке, полученный фрейм данных - беспорядок . Так как некоторые html таблицы имеют больше записей, чем другие (сравните this и this , несколько адресов является обычным явлением), значения повсюду: (Примечание что некоторые были вырезаны ~ форматированием таблицы)
> as_tibble(web_data)
# A tibble: 13 x 13
X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13
<chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 090978~ Mitte Gesund~ Putbuss~ 12 Swinemünder~ Gesamtanlage Schule & B~ NA NA NA NA NA
2 090978~ Charlotten~ Westend Messeda~ 11 & 12 Hammarskjöl~ Baudenkmal Kongressge~ NA NA NA NA NA
3 090978~ Mitte Tierga~ Rauchst~ 4 & 5 & 6 Stülerstraße 2 & 4 Thomas-Deh~ 1 & 3 ~ Gartendenkm~ Siedlungs~ NA NA
4 090978~ Reinickend~ Tegel Am Tege~ 2 & 4 & 6 & 8 & 8A & 8B & 8C & 8D & 8E & 10~ Gartendenkm~ Siedlungsgr~ NA NA NA NA NA NA
5 090978~ Charlotten~ Wilmer~ Prager ~ 4 & 5 Prager Stra~ 13 Prinzregen~ 97 Asschaffenb~ Gesamtanl~ Stadt~ NA
6 090978~ Mitte Tierga~ Reichpi~ 48 & 50 Gesamtanlage Forschungse~ NA NA NA NA NA NA
7 090978~ Mitte Tierga~ Rauchst~ 4 & 5 & 6 Stülerstraße 2 & 4 Thomas-Deh~ 1 & 3 ~ Gesamtanlage Wohnanlage NA NA
8 090978~ Mitte Tierga~ Pohlstr~ 77 Baudenkmal Wohn- und G~ NA NA NA NA NA NA
9 090978~ Mitte Tierga~ Lützowu~ 1A & 1B & 2 & 2A & 3 & 3A & 4 & 4A & 5 & 5A Gesamtanlage Wohnanlage NA NA NA NA NA NA
10 090978~ Mitte Tierga~ Lützows~ 44 & 44A & 45 & 45A & 45B & 45C & 45D & 45E~ Gesamtanlage Wohnanlage ~ NA NA NA NA NA NA
Мне нужно название каждой улицы (например, «Pohlstr (aße)», «Stülerstraße») для каждого здания в столбце со всеми названия других улиц, все типы зданий (например, «Wohnanlage», «Schule») в столбце et c. Как я могу этого добиться?
Я уже пробовал соскабливать целые html таблицы в фрейм данных, но это дало аналогичные результаты. У меня нет способа узнать максимальное количество записей, кроме как запустить все l oop для всех 12k html сайтов. (Кроме того, если мой существующий код можно как-то улучшить, не стесняйтесь давать советы