我正在尝试抓取一个网站,该网站包含我在段落中想要的许多不同信息。我使它可以完美工作...但是,我不知道如何分解文本并创建数据框。
代码:
library(rvest)
url <- "https://www.state.nj.us/treasury/administration/statewide-support/motor-fuel-locations.shtml"
#Reading the HTML code from the website
webpage <- read_html(url)
p_nodes<-webpage%>%
html_nodes(xpath = '//p')%>%
html_text()
#replace multiple whitespaces with single space
p_nodes<- gsub('\\s+',' ',p_nodes)
#trim spaces from ends of elements
p_nodes <- trimws(p_nodes)
#drop blank elements
p_nodes <- p_nodes[p_nodes != '']
我希望数据框如何显示:
我不确定这是否可能。我试图分别提取每条信息,然后像这样制作数据框,但是由于大多数信息都存储在p标记中,因此它不起作用。我将不胜感激。谢谢!
答案 0 :(得分:1)
概念验证(基于我在评论中写的内容):
代码
lapply(c('data.table', 'httr', 'rvest'), library, character.only = T)
tags <- 'tr:nth-child(6) td , tr~ tr+ tr p , td+ p'
burl <- 'https://www.state.nj.us/treasury/administration/statewide-support/motor-fuel-locations.shtml'
url_text <- read_html(burl)
chunks <- url_text %>% html_nodes(tags) %>% html_text()
coordFunc <- function(chunk){
patter_lat <- 'Longitude:.*(-[[:digit:]]{1,2}.[[:digit:]]{0,15})'
ret <- regmatches(x = chunk, m = regexec(pattern = patter_lat, text = chunk))
return(ret[[1]][2])
}
longitudes <- as.numeric(unlist(lapply(chunks, coordFunc)))
输出
# using 'cat' to make the output easier to read
> cat(chunks[14])
Mt. Laurel DOT
Rt. 38, East
1/4 mile East of Rt. 295
Mt. Laurel Open 24 Hrs
Unleaded / Diesel
856-235-3096Latitude: 39.96744662Longitude: -74.88930386
> longitudes[14]
[1] -74.8893
如果您不强迫longitudes
成为numeric
,则会得到:
longitudes <- (unlist(lapply(chunks, coordFunc)))
> longitudes[14]
[1] "-74.88930386"
我选择了经度作为概念验证,但是您可以修改函数以在单个调用中提取所有相关位。为了获得正确的tag
,您可以使用SelectorGadget扩展程序(在Chrome浏览器中对我来说效果很好)。通常,大多数浏览器都允许您“检查元素”以获取html
标签。该函数可以将提取的值返回到data.table
中,然后可以使用rbindlist
将其合并为一个值。
您甚至可以通过编程方式推进页面以抓取整个网站-请务必查看使用政策(通常不赞成或仅限于抓取网站)。
修改
文本在整个网页中的结构不同,因此您需要花费更多时间检查可能发生的异常。
这是一个新功能,用于将每个块解析为单独的行,然后您可以尝试使用其他正则表达式来获取所需的内容。
newfunc <- function(chunk){
# Each chunk is a couple of lines. First, we split at '\r\n' using strsplit
# the output is a list so we use 'unlist' to get a vector
# then use 'trimws' to remove whitespace around it - try out each of these functions
# separately to understand what is going on. The final output here is a vector.
txt <- trimws(unlist(strsplit(chunk, '\r\n')))
return(txt)
}
这将返回每个块中包含的“文本”作为单独行的向量。看一下前20个块中的行数,您会发现它是不同的:
> unlist(lapply(chunks[1:20], function(z) length(newfunc(z))))
[1] 5 6 5 7 5 5 5 5 5 4 1 6 6 6 5 1 1 1 5 6
解决此问题的一种好方法是根据每个块中的文本行数(例如在newfunc
中,您可以添加:
if(length(txt) == 1){
return(NULL)
}
这是因为这是针对其中没有任何文本的条目的。由于这是概念验证,因此我没有检查所有条目,但是有一些简单的逻辑:
unleaded
或diesel
。您可以在这两个字符串上grep
来查看每个仓库提供的内容。例如grepl('diesel', newfunc(chunks[12]))
html
标签,例如所有协调和开放时间均以黑体显示,并带有标签strong
。您可以分别提取它们,然后使用正则表达式获取所需的内容。 24(Hrs|Hours)
,以首先提取所有24小时开放的网站,然后对其余部分使用选择性的regex
,以获取其运行时间。 对于大多数网络抓取,没有简单容易的答案,您必须找到模式,然后基于此模式应用一些逻辑。只有在结构最完整的网站上,您才能找到适用于整个页面/范围的内容。
答案 1 :(得分:0)
您可以使用tidyverse程序包(stringr,tibble,purrr)
library(rvest)
library(tidyverse)
url <- "https://www.state.nj.us/treasury/administration/statewide-support/motor-fuel-locations.shtml"
#Reading the HTML code from the website
webpage <- read_html(url)
p_nodes<-webpage%>%
html_nodes(xpath = '//p')%>%
html_text()
# Split on new line
l = p_nodes %>% stringr::str_split(pattern = "\r\n")
var1 = sapply(l, `[`, 1) # replace var by the name you want
var2 = sapply(l, `[`, 2)
var3 = sapply(l, `[`, 3)
var4 = sapply(l, `[`, 4)
var5 = sapply(l, `[`, 5)
t = tibble(var1,var2,var3,var4,var5) # make tibble
t = t %>% filter(!is.na(var2)) # delete useless lines
purrr::map_dfr(t,trimws) # delete blanks