具有困难节点的网页抓取分页网站
Web-scraping paginated website with difficult node
我正在抓取 ASN 数据库 (http://aviation-safety.net/database/)。我编写了代码来对每一年 (1919-2019) 进行分页,并抓取除死亡人数以外的所有相关节点(表示为 "fat.")。 Selector Gadget 告诉我死亡节点称为“'#contentcolumnfull :nth-child(5)'”。出于某种原因,“.list:nth-child(5)”不起作用。
当我抓取#contentcolumnfull :nth-child(5) 时,第一个元素是空白的,表示为“”。
我如何编写一个函数来删除每个被抓取的 year/page 的第一个空元素?当我自己抓取单个页面时,删除第一个元素很简单:
fat <- html_nodes(webpage, '#contentcolumnfull :nth-child(5)')
fat <- html_text(fat)
fat <- fat[-1]
但我发现很难写入函数。
我还有一个关于日期时间和格式的问题。我的天数数据表示为日-月-年。缺少几个元素日和月(例如:??-??-1985、JAN-??-2004)。理想情况下,我想将日期转换为 lubridate 对象,但我不能丢失数据或者只保留年份。
至此,我使用了 gsub() 和正则表达式来清理数据(删除“??”和浮动破折号),所以我有多种数据格式。然而,这使得数据可视化变得困难。关于最佳实践的想法?
# Load libraries
library(tidyverse)
library(rvest)
library(xml2)
library(httr)
years <- seq(1919, 2019, by=1)
pages <- c("http://aviation-safety.net/database/dblist.php?Year=") %>%
paste0(years)
# Leaving out the category, location, operator, etc. nodes for sake of brevity
read_date <- function(url){
az <- read_html(url)
date <- az %>%
html_nodes(".list:nth-child(1)") %>%
html_text() %>%
as_tibble()
}
read_type <- function(url){
az <- read_html(url)
type <- az %>%
html_nodes(".list:nth-child(2)") %>%
html_text() %>%
as_tibble()
}
date <- bind_rows(lapply(pages, read_date))
type <- bind_rows(lapply(pages, read_type))
# Writing to dataframe
aviation_df <- cbind(type, date)
aviation_df <- data.frame(aviation_df)
# Excluding data cleaning
多次 ping 同一个页面以提取请求的信息是不好的做法。您应该阅读该页面,提取所有需要的信息,然后移至下一页。
在这种情况下,各个节点都存储在一个主节点中 table。 rvest 的 html_table()
函数可以方便地将 html table 转换为数据框。
library(rvest)
library(dplyr)
years <- seq(2010, 2015, by=1)
pages <- c("http://aviation-safety.net/database/dblist.php?Year=") %>%
paste0(years)
# Leaving out the category, location, operator, etc. nodes for sake of brevity
read_table <- function(url){
#add delay so that one is not attacking the host server (be polite)
Sys.sleep(0.5)
#read page
page <- read_html(url)
#extract the table out (the data frame is stored in the first element of the list)
answer<-(page %>% html_nodes("table") %>% html_table())[[1]]
#convert the falatities column to character to make a standardize column type
answer$fat. <-as.character(answer$fat.)
answer
}
# Writing to dataframe
aviation_df <- bind_rows(lapply(pages, read_table))
有一些额外的列需要清理
我正在抓取 ASN 数据库 (http://aviation-safety.net/database/)。我编写了代码来对每一年 (1919-2019) 进行分页,并抓取除死亡人数以外的所有相关节点(表示为 "fat.")。 Selector Gadget 告诉我死亡节点称为“'#contentcolumnfull :nth-child(5)'”。出于某种原因,“.list:nth-child(5)”不起作用。
当我抓取#contentcolumnfull :nth-child(5) 时,第一个元素是空白的,表示为“”。
我如何编写一个函数来删除每个被抓取的 year/page 的第一个空元素?当我自己抓取单个页面时,删除第一个元素很简单:
fat <- html_nodes(webpage, '#contentcolumnfull :nth-child(5)')
fat <- html_text(fat)
fat <- fat[-1]
但我发现很难写入函数。
我还有一个关于日期时间和格式的问题。我的天数数据表示为日-月-年。缺少几个元素日和月(例如:??-??-1985、JAN-??-2004)。理想情况下,我想将日期转换为 lubridate 对象,但我不能丢失数据或者只保留年份。
至此,我使用了 gsub() 和正则表达式来清理数据(删除“??”和浮动破折号),所以我有多种数据格式。然而,这使得数据可视化变得困难。关于最佳实践的想法?
# Load libraries
library(tidyverse)
library(rvest)
library(xml2)
library(httr)
years <- seq(1919, 2019, by=1)
pages <- c("http://aviation-safety.net/database/dblist.php?Year=") %>%
paste0(years)
# Leaving out the category, location, operator, etc. nodes for sake of brevity
read_date <- function(url){
az <- read_html(url)
date <- az %>%
html_nodes(".list:nth-child(1)") %>%
html_text() %>%
as_tibble()
}
read_type <- function(url){
az <- read_html(url)
type <- az %>%
html_nodes(".list:nth-child(2)") %>%
html_text() %>%
as_tibble()
}
date <- bind_rows(lapply(pages, read_date))
type <- bind_rows(lapply(pages, read_type))
# Writing to dataframe
aviation_df <- cbind(type, date)
aviation_df <- data.frame(aviation_df)
# Excluding data cleaning
多次 ping 同一个页面以提取请求的信息是不好的做法。您应该阅读该页面,提取所有需要的信息,然后移至下一页。
在这种情况下,各个节点都存储在一个主节点中 table。 rvest 的 html_table()
函数可以方便地将 html table 转换为数据框。
library(rvest)
library(dplyr)
years <- seq(2010, 2015, by=1)
pages <- c("http://aviation-safety.net/database/dblist.php?Year=") %>%
paste0(years)
# Leaving out the category, location, operator, etc. nodes for sake of brevity
read_table <- function(url){
#add delay so that one is not attacking the host server (be polite)
Sys.sleep(0.5)
#read page
page <- read_html(url)
#extract the table out (the data frame is stored in the first element of the list)
answer<-(page %>% html_nodes("table") %>% html_table())[[1]]
#convert the falatities column to character to make a standardize column type
answer$fat. <-as.character(answer$fat.)
answer
}
# Writing to dataframe
aviation_df <- bind_rows(lapply(pages, read_table))
有一些额外的列需要清理