我正在尝试使用rvest
来获取Whole Foods商店的列表。我已经成功使用这种技术从Wikipedia,FIFA,Yahoo!获取信息。财务等等,但是此“表”涵盖了多个页面,但所有页面都有相同的url。抱歉,我不是最擅长HTML的人,也不知道所讨论项目类型的正确名称。
我的问题:我不仅能获得第一页数据,还能获得更多信息吗?
额外信用:我只需要知道邮政编码的邮政编码即可。如果您想挑战自己并弄清楚如何提取地址,那可能会有所帮助!问题是地址和城市没有定界符合并在一起。我在想类似在小写字母之后立即寻找大写字母的情况,但是在某些情况下,地址以大写字母结尾。
下面的代码:
get_markets <- function() {
url <- "https://www.wholefoodsmarket.com/stores/list/state"
xpath <- '//*[@id="block-views-store-locations-by-state-
state"]/div/div/div[3]'
selector <- "#block-views-store-locations-by-state-state"
tbl <- url %>%
read_html() %>%
html_nodes(css = selector) %>% # or xpath = xpath
.[[1]] %>%
html_text(trim = TRUE) %>%
strsplit('\\s*\\n\\s*') %>%
unlist() %>%
.[-c(1:3)] %>%
matrix(ncol = 7, byrow = TRUE) %>%
as.data.frame(stringsAsFactors = FALSE) %>%
mutate(
zip = stringr::str_extract(V2, "(?<= )\\d{5}(?=U|-)")
) %>%
select(store = V1, zip) %>%
na.omit()
}
答案 0 :(得分:1)
底部的页面链接提供了您需要抓取的页面。如果您查看href,它们会遵循以下模式:https://www.wholefoodsmarket.com/stores/list/state?page=1
,state?page=2
等,其中第一页是?page=0
,因此您可以使用{{1} }和paste
。
在抓取之前,如果您查看the site's robots.txt,它指定的爬网延迟为10秒,因此我们需要添加一个seq
调用以减慢抓取速度。
从策略角度来说,对于每个页面,选择所有存储,然后对那些节点进行迭代并提取所需的片段。该地址的格式为多个Sys.sleep
,因此分别在它们上调用div
并将其折叠为换行符分隔的字符串将使其更加有用。
使用purrr进行迭代(purrr具有列表和html_text
的功能使其成为rvest的重要补充),
map_dfr
从此处,使用正则表达式或地址解析器(如果需要)将邮政编码从地址中拉出。
答案 1 :(得分:0)
弄清楚了。下面是我的解决方案。可能更好一些:
library(tidyverse)
library(rvest)
get_url <- function(page) {
if (page == 0) {
url <- "https://www.wholefoodsmarket.com/stores/list/state"
} else {
url <- paste0("https://www.wholefoodsmarket.com/stores/list/state?page=", page)
}
return(url)
}
get_last <- function() {
url <- "https://www.wholefoodsmarket.com/stores/list/state"
xpath <- '//*[@id="block-views-store-locations-by-state-state"]/div/div/div[4]/ul/li[11]/a'
out <- url %>%
read_html() %>%
html_nodes(xpath = xpath) %>%
html_text() %>%
as.numeric()
}
get_markets <- function(page) {
url <- get_url(page)
xpath <- '//*[@id="block-views-store-locations-by-state-state"]/div/div/div[3]'
selector <- "#block-views-store-locations-by-state-state"
tbl <- url %>%
read_html() %>%
html_nodes(css = selector) %>%
.[[1]] %>%
html_text(trim = TRUE) %>%
strsplit('\\s*\\n\\s*') %>%
unlist() %>%
.[-c(1:3)] %>%
matrix(ncol = 7, byrow = TRUE) %>%
as.data.frame(stringsAsFactors = FALSE) %>%
mutate(
zip = stringr::str_extract(V2, "(?<= )\\d{5}(?=U|-)")
) %>%
select(store = V1, zip) %>%
na.omit()
return(tbl)
}
markets <- list()
for (i in 1:get_last()) {
markets[[i]] <- get_markets(i-1)
}
markets <- Reduce(rbind, markets)