【问题标题】:Scraping table from timeanddate.com using R使用 R 从 timeanddate.com 抓取表格
【发布时间】:2021-01-05 14:14:29
【问题描述】:

我正在尝试在以下网页上抓取 3 月 2 日的天气数据(以 R 表示):https://www.timeanddate.com/weather/sweden/stockholm/historic?month=3&year=2020 我对末尾的表格感兴趣,位于“斯德哥尔摩天气历史...”下方/p>

该表的正上方和右侧是一个下拉列表,我在其中选择了 3 月 2 日。但是当我使用 rselenium 进行抓取时,我只能得到 3 月 1 日的数据。 如何获取第二个(以及除第一个以外的任何其他日期)的数据 我也尝试使用 read_html 抓取整个页面,但我找不到从中提取我想要的数据的方法。

以下代码似乎仅适用于该月的第一天,但​​适用于该月的任何其他日期。

library(tidyverse)
library(rvest)
library(RSelenium)
library(stringr)
library(dplyr)
rD <- rsDriver(browser="chrome", port=4234L, chromever ="85.0.4183.83")
remDr <- rD[["client"]]
remDr$navigate("https://www.timeanddate.com/weather/sweden/stockholm/historic?month=3&year=2020")
webElems <- remDr$findElements(using="class name", value="sticky-wr")
s<-webElems[[1]]$getElementText()
s<-as.character(s)
print(s)

【问题讨论】:

标签: r web-scraping rselenium


【解决方案1】:

这是一种使用 RSelenium 的方法

library(RSelenium)
library(rvest)
driver <- rsDriver(browser="chrome", port=4234L, chromever ="87.0.4280.87")
client <- driver[["client"]]
client$navigate("https://www.timeanddate.com/weather/sweden/stockholm/historic?month=3&year=2020")
client$findElement(using = "link text","Mar 2")$clickElement()
source <- client$getPageSource()[[1]]
read_html(source) %>%
   html_node(xpath = '//*[@id="wt-his"]') %>%
   html_table %>%
   head
                     Conditions Conditions      Conditions Comfort Comfort  Comfort                     
1               Time                  Temp         Weather    Wind         Humidity Barometer Visibility
2 12:20 amMon, Mar 2                 39 °F         Chilly.   7 mph       ↑      87% 29.18 "Hg        N/A
3           12:50 am                 37 °F         Chilly.   7 mph       ↑      87% 29.18 "Hg        N/A
4            1:20 am                 37 °F Passing clouds.   7 mph       ↑      87% 29.18 "Hg        N/A
5            1:50 am                 37 °F Passing clouds.   7 mph       ↑      87% 29.18 "Hg        N/A
6            2:20 am                 37 °F       Overcast.   8 mph       ↑      87% 29.18 "Hg        N/A

然后您可以迭代 findElement() 的日期。

您可以通过右键单击表格并在 Chrome 中选择 Inspect 来找到 xpath:

然后,您可以找到表格元素,右键单击并选择“复制”>“复制 XPath”。

【讨论】:

  • 比我的解决方案好多了。我需要看看 RSelenium。
【解决方案2】:

使用浏览器的“开发人员工具”检查网页并找出如何提取所需信息总是有用的。

我刚刚在谷歌上搜索了一些解释这一点的教程:

https://towardsdatascience.com/tidy-web-scraping-in-r-tutorial-and-resources-ac9f72b4fe47 https://www.scrapingbee.com/blog/web-scraping-r/

例如,在这个特定的网页中,当我们在下拉列表中选择一个新的日期时,该网页向服务器发送一个 GET 请求,服务器返回一个带有请求日期数据的 JSON 字符串。然后网页更新表中的数据(可能使用javascript——没有检查这个)。

因此,在这种情况下,您需要模拟这种行为,捕获 json 文件并解析其中的信息。

在 Chrome 中,如果你查看开发者工具的网络面板,你会看到 GET 请求的地址是这样的:

https://www.timeanddate.com/scripts/cityajax.php?n=sweden/stockholm&mode=historic&hd=YYYYMMDD&month=M&year=YYYY&json=1

其中,YYYY 代表 4 位数字的年份,MM(M) 代表两(一)位数字的月份,DD 代表两位数字的月份。

因此,您可以将代码设置为直接向该地址发出 GET 请求,获取 json 响应并进行相应的解析。

library(rjson)
library(rvest)
library(plyr)
library(dplyr)

year <- 2020
month <- 3
day <- 7

# create formatted url with desired dates
url <- sprintf('https://www.timeanddate.com/scripts/cityajax.php?n=sweden/stockholm&mode=historic&hd=%4d%02d%02d&month=%d&year=%4d&json=1', year, month, day, month, year)

webpage <- read_html(url) %>% html_text()

# json string is not formatted the way fromJSON function needs
# so I had to parse it manually

# split string on each row
x <- strsplit(webpage, "\\{c:")[[1]]
# remove first element (garbage)
x <- x[2:length(x)]
# clean last 2 characters in each row
x <- sapply(x, FUN=function(xx){substr(xx[1], 1, nchar(xx[1])-2)}, USE.NAMES = FALSE)

# function to get actual data in each row and put it into a dataframe

parse.row <- function(row.string) {
  # parse columns using '},{' as divider
  a <- strsplit(row.string, '\\},\\{')[[1]]
  # remove some lefover characters from parsing
  a <- gsub('\\[\\{|\\}\\]', '', a)
  # remove what I think is metadata
  a <- gsub('h:', '', gsub('s:.*,', '', a))
  
  df <- data.frame(time=a[1], temp=a[3], weather=a[4], wind=a[5], humidity=a[7],
                   barometer=a[8])
  
  return(df)
}

# use ldply to run function parse.row for each element of x and combine the results in a single dataframe
df.final <- ldply(x, parse.row)

结果:

> head(df.final)
                  time    temp           weather      wind humidity     barometer
1 "12:20 amSat, Mar 7" "28 °F" "Passing clouds." "No wind"   "100%" "29.80 \\"Hg"
2           "12:50 am" "28 °F" "Passing clouds." "No wind"   "100%" "29.80 \\"Hg"
3            "1:20 am" "28 °F" "Passing clouds."   "1 mph"   "100%" "29.80 \\"Hg"
4            "1:50 am" "30 °F" "Passing clouds."   "2 mph"   "100%" "29.80 \\"Hg"
5            "2:20 am" "30 °F" "Passing clouds."   "1 mph"   "100%" "29.80 \\"Hg"
6            "2:50 am" "30 °F"     "Low clouds." "No wind"   "100%" "29.80 \\"Hg"

我将所有内容都作为字符串保留在数据框中,但您可以根据需要将列转换为数字或日期。

【讨论】:

  • 我尝试了hd= 方法,但无法让它发挥作用,这令人印象深刻。
猜你喜欢
  • 2019-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-28
  • 2021-06-07
  • 1970-01-01
  • 2013-11-16
  • 1970-01-01
相关资源
最近更新 更多