R语言rvest爬取天气网中的历史天气信息
整体思路
我们进入天气网首页:http://lishi.tianqi.com/,以广州2017年09月历史天气为例,把当前页面切换到广州天气页面,如下图:
继续往下滚动页面,直到看到广州历史天气详情,然后点击2017年09月天气 ,进入广州2017年09月天气详情页面,如下图:
注意链接地址的变化:链接中的guangzhou代表地区,201709代表时间。也就是说我们可以通过控制这两个参数,跳转到任意地区和时间的历史天气状况页面。
现在我们看下广州地区201709[http://lishi.tianqi.com/guang...页面的详细信息,滚动页面,可以找到我们想要爬取的数据:
现在,我们已经有了大概的思路:
- 先实现如何抓取某一特定页面的数据,例如广州地区2017年09月的历史数据。
- 通过控制地区和时间这两个参数,并利用1中的方法,实现多地区或多时间的历史天气数据抓取。
不难看出,我们的重点是如何解决第一个问题。只要把第一问中的方法包装成函数,就可以通过调节参数解决第二个问题。
抓取特定页面的数据
我们需要在浏览器中调试js代码,chrome中按F12即可查看。通过搜索关键字:日期,最高气温 ...任何一个都行,得到以下信息。可以发现我们所需要的数据都在<div class="tqtongji2">盒子中,而每一行数据又都在ul中。所以,我们可以通过这两个特征来提取数据。
获取<div class="tqtongji2">以及ul中内容的R代码如下:
library(rvest) library(plyr) city <- 'guangzhou' date <- '201709' baseUrl <- 'http://lishi.tianqi.com/' Url <- paste(baseUrl, city, '/', date, '.html', sep = '') content <- Url %>% read_html(encoding='GBK') %>% html_nodes('div.tqtongji2') %>% html_nodes("ul") %>% html_text() head(content)
content的内容如下:
[1] "日期\r\n\t\t 最高气温\r\n\t\t 最低气温\r\n\t\t 天气\r\n\t\t 风向\r\n\t\t 风力\r\n\t\t " [2] "2017-09-01\r\n\t\t \t\t\t \t35\r\n\t\t \t26\r\n\t\t \t雷阵雨\r\n\t\t \t东北风\r\n\t\t \t1级\r\n \t " [3] "2017-09-02\r\n\t\t \t\t\t \t35\r\n\t\t \t26\r\n\t\t \t雷阵雨\r\n\t\t \t东风\r\n\t\t \t1级\r\n \t " [4] "2017-09-03\r\n\t\t \t\t\t \t34\r\n\t\t \t25\r\n\t\t \t雷阵雨\r\n\t\t \t东北风\r\n\t\t \t2级\r\n \t " [5] "2017-09-04\r\n\t\t \t\t\t \t30\r\n\t\t \t25\r\n\t\t \t中雨\r\n\t\t \t东南风\r\n\t\t \t微风\r\n \t "
我们可以发现数据之间用rntt之类的隔开。而'rntt'这些里面有:回车符,换行符和制表符。他们的共同点就是全都是空格。所以我们可以通过空格来进行分列,提取相应的数据。
content <- content %>% strsplit("\\s{4,}") content
输出结果为列表的形式:
[[1]] [1] "日期" "最高气温" "最低气温" "天气" "风向" "风力" [[2]] [1] "2017-09-01" "35" "26" "雷阵雨" "东北风" "1级" [[3]] [1] "2017-09-02" "35" "26" "雷阵雨" "东风" "1级" [[4]] [1] "2017-09-03" "34" "25" "雷阵雨" "东北风" "2级"
为了美观和方便操作,我们把它转换为数据框的形式:
content <- ldply(content[-1]) names(content) <- c('date', 'highDegree', 'lowDegree', 'weather', 'windDirection', 'windForce')
至此,我们已经成功获取这个页面中的数据:
date highDegree lowDegree weather windDirection windForce 1 2017-09-01 35 26 雷阵雨 东北风 1级 2 2017-09-02 35 26 雷阵雨 东风 1级 3 2017-09-03 34 25 雷阵雨 东北风 2级 4 2017-09-04 30 25 中雨 东南风 微风 5 2017-09-05 33 26 雷阵雨 东风 1级 6 2017-09-06 33 26 雷阵雨 南风 1级
定义可以传递参数的抓取函数
我们将上述中的代码,进行整理,封装成一个函数,如下:
library(rvest) library(data.table) library(plyr) fetchData <- function(city, date){ baseUrl <- 'http://lishi.tianqi.com/' Url <- paste(baseUrl, city, '/', date, '.html', sep = '') content <- Url %>% read_html(encoding='GBK') %>% html_nodes('div.tqtongji2') %>% html_nodes("ul") %>% html_text() %>% strsplit("\\s{4,}") content <- ldply(content[-1]) names(content) <- c('date', 'highDegree', 'lowDegree', 'weather', 'windDirection', 'windForce') return(content) }
这时候,我们可以调用上述函数,并通过传递地区city和时间date参数来爬取相应的数据。例如,爬取北京地区2017年09月的历史天气:
beijing <- fetchData(city = 'beijing', date = '201709') head(beijing)
date highDegree lowDegree weather windDirection windForce 1 2017-09-01 27 19 多云 西南风 2级 2 2017-09-02 27 19 多云 西南风 2级 3 2017-09-03 29 19 多云 南风 2级 4 2017-09-04 28 20 阴 南风 2级 5 2017-09-05 30 18 多云 西北风 2级 6 2017-09-06 31 18 晴 西南风 2级
当然如果你想爬取北京地区2016年的全年天气状况,可以利用上面的函数,通过循环,合并得到你想要的数据。