整体思路
我们进入天气网首页: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年的全年天气状况,可以利用上面的函数,通过循环,合并得到你想要的数据。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。