首页 > 解决方案 > Scrape Web Page When Selector Does Not Update URL

问题描述

我正在尝试为给定的区域和时间(例如“Onslow”、“Yesterday”)抓取此网页(https://nc.211counts.org)。我想从左上角的表格中提取所有信息(COVID、住房等通过其他)。不幸的是,选择过滤器时 URL 不会更新。我一直在关注这里的教程,但找不到一种方法来拉入我需要抓取的区域名称的位置。由于html_nodes函数返回空,我认为映射有一些东西是关闭的。

我在这里想念什么?

# docker run -d -p 4445:4444 selenium/standalone-chrome
# docker ps

remDr <- RSelenium::remoteDriver(remoteServerAddr = "localhost",
                                 port = 4445L,
                                 browserName = "chrome")
remDr$open()

remDr$navigate("https://nc.211counts.org") 
remDr$screenshot(display = TRUE) 
nc211 <- xml2::read_html(remDr$getPageSource()[[1]]) 

str(nc211)

body_nodes <- nc211 %>% 
  html_node('body') %>% 
  html_children()

body_nodes

body_nodes %>% 
  html_children()

rank <- nc211 %>% 
  rvest::html_nodes('body') %>% 
  xml2::xml_find_all("//span[contains(@class, 'col-lg-12 chosen-select')]") %>% 
  rvest::html_text()

# this returns empty
nc211 %>%
  rvest::html_nodes("#region") %>%
  rvest::html_children() %>%
  rvest::html_text() 

# guessing at an element number to see what happens
element<- remDr$findElement(using = 'css selector', "#region > option:nth-child(1)")
element$clickElement()

标签: htmlrweb-scraping

解决方案


当您做出选择并按下搜索时,内容会通过 xhr POST 请求动态更新。您可以使用网络选项卡来分析这些请求并在不使用 selenium 的情况下重现它们(作为替代方案)。您将需要从初始页面中获取参数选项。

在此处输入图像描述

下面我将向您展示如何请求特定邮政编码,以及如何找出所有邮政编码及其相应的参数 ID 以在请求中使用。后者需要来自初始 url。

library(httr)
library(rvest)


data = list(
  'id' = '{"ids":["315"]}', # zip 27006 is id 315 seen in value attribute of checkbox node 
  'timeIntervalId' = '18',
  'centerId' = '7',
  'type' = 'Z'
)
#post request that page makes using your filter selections e.g. zip code
r <- httr::POST(url = 'https://nc.211counts.org/dashBoard/barChart',  body = data) 
page <- read_html(r)
categories <- page %>% html_nodes(".categoriesDiv  .toolTipSubCategory, #totalLabel") %>% html_text
colNodes <- page %>% html_nodes(".categoriesDiv .value")
percentages <- colNodes %>% html_attr('data-percentage')
counts <- colNodes %>% html_attr('data-value')

df <- as.data.frame(cbind(categories, percentages, counts)) 
print(df)

#Lookups e.g. zip codes. Taken from initial url
initial_page <- read_html('https://nc.211counts.org/')
ids <- initial_page %>% html_nodes('.zip [value]') %>% html_attr('value')
zips <- initial_page %>% html_nodes('.zip label') %>% html_text() %>% trimws()

print(ids[match('27006', zips)])

推荐阅读