获取使用rvest的全食商店列表

时间:2018-07-01 15:17:59

标签: html r web-scraping html-parsing rvest

我正在尝试使用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()
}

2 个答案:

答案 0 :(得分:1)

底部的页面链接提供了您需要抓取的页面。如果您查看href,它们会遵循以下模式:https://www.wholefoodsmarket.com/stores/list/state?page=1state?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)