概念证明(基于我在评论中写的):
代码
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个chunk的行数,不一样的:
> 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 以获取其运行时间。
大多数网络抓取没有简单的简单答案,您必须找到模式,然后在此基础上应用一些逻辑。只有在最结构化的网站上,您才能找到适用于整个页面/范围的内容。