【问题标题】:Scraping data from web into dataframe with rvest使用 rvest 将数据从 Web 抓取到数据框中
【发布时间】:2019-12-03 20:51:28
【问题描述】:

我有一个关于将网页中的数据抓取到数据框中的问题...我有一个脚本可以工作,但可以改进,我正在努力实现我想要的改进。

在谷歌搜索和阅读 StackOverflow 材料的帮助下,我制作了一个脚本,该脚本使用许可证编号列表从 EPA 网站获取 NPDES SIC 代码数据。

library(rvest)
library(tidyverse)

# Start with permit number list 

permitlist <- list("DC0000175", "VA0076384", "VA0021318")

# For each permit number, create a URL list that leads to the EPA site associated with that permit

urls <- list()
for(i in 1:length(permitlist)) {
  url <- paste0("https://iaspub.epa.gov/enviro/fii_query_dtl.disp_program_facility?pgm_sys_id_in=", permitlist[i], "&pgm_sys_acrnm_in=NPDES")
urls[i] <- url
} 

# Open each URL and scrape SIC code data

complete<-data.frame()
tbl <- list()

for (j in seq_along(urls)) {
  data <- tbl[[j]] <- urls[[j]] %>%  
    read_html() %>% 
    html_nodes("tr") %>%
    html_text()
  data <- unlist(strsplit(trimws(grep("^NPDES\n", tbl[[j]], value=TRUE)[1]), "\n", perl=TRUE))
  complete <-rbind(complete,data, stringsAsFactors = FALSE)
  }

输出表如下所示:


1    NPDES    3273                READY-MIXED CONCRETE
2    NPDES    3714                MOTOR VEHICLE PARTS AND ACCESSORIES
3    NPDES    4952                SEWERAGE SYSTEMS

# (Row number, type of permit (all will be NPDES), NPDES SIC code, and description.)

我想编辑脚本,以便数据框包含许可证编号列。此外,一些许可证号码有多个 NPDES SIC 代码(例如:https://iaspub.epa.gov/enviro/fii_query_dtl.disp_program_facility?pgm_sys_id_in=DC0000175&pgm_sys_acrnm_in=NPDES 的 DC0000175 有两个 NPDES SIC 代码),但我只能获取获取第一个 SIC 代码的脚本。

理想情况下,我的最终数据框应如下所示:


1    NPDES    3273    DC0000175  READY-MIXED CONCRETE
2    NPDES    1611    DC0000175  HIGHWAY AND STREET CONSTRUCTION, EXCEPT ELEVATED HIGHWAYS
3    NPDES    3714    VA0076384  MOTOR VEHICLE PARTS AND ACCESSORIES
4    NPDES    4952    VA0021318  SEWERAGE SYSTEMS

我一直在努力让它工作一段时间,希望能提供任何帮助。

【问题讨论】:

    标签: r web-scraping rvest


    【解决方案1】:

    进行两项更改:

    • 使用 c() 将许可列表从列表更改为向量 - 这也使其运行速度更快!
    • 在您的data df 中添加一个新列并分配相应的许可值
    library(rvest)
    library(tidyverse)
    
    # Start with permit number list 
    
    # vector is more efficient and more easily iterable
    permitlist <- c("DC0000175", "VA0076384", "VA0021318")
    
    # For each permit number, create a URL list that leads to the EPA site associated with that permit
    
    urls <- list()
    for(i in 1:length(permitlist)) {
      url <- paste0("https://iaspub.epa.gov/enviro/fii_query_dtl.disp_program_facility?pgm_sys_id_in=", permitlist[i], "&pgm_sys_acrnm_in=NPDES")
      urls[i] <- url
    } 
    
    # Open each URL and scrape SIC code data
    
    complete<-data.frame()
    tbl <- list()
    
    for (j in seq_along(urls)) {
      tbl[[j]] <- urls[[j]] %>%  
        read_html() %>% 
        html_nodes("tr") %>%
        html_text()
    
      data <- data.frame(A = NA, B = NA, c = NA, permit = NA)
      a <- grep("^NPDES\n", tbl[[j]], value=TRUE)
    
      for(k in seq_along(a)){
      dt <- unlist(strsplit(trimws(a[k]), "\n", perl=TRUE))
      dt <- c(dt, permitlist[j])
      data[k,] <- dt
      }
      complete <- bind_rows(complete, data)
    
    }
    
    complete
    

    已编辑,通过在填充表格之前分配列名(A、B、C、permit),使输出数据帧更加整洁。

    已编辑 2:现在从每个 url 调用中获取多个项目

    【讨论】:

    • 谢谢你,向量确实有助于让事情进展得更快!我仍然希望脚本将许可证的所有 SIC 代码作为单独的行返回,而不仅仅是第一个代码,但我想我可以进行第二个循环,使用 (grep("^NPDES\n", tbl[[j]], value=TRUE)[2]),然后合并数据帧。
    • 哎呀,抱歉没有注意到,所以从每个 url 获取所有结果。已更新代码,第一个中间的新 for 循环将遍历每个 url 的所有结果。同样,您可以在第一个循环中更改 data 定义中的列名。希望有帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-03
    • 2016-10-05
    • 2020-10-05
    • 2019-05-31
    • 2017-04-01
    相关资源
    最近更新 更多