2

整体思路

我们进入天气网首页:http://lishi.tianqi.com/,以广州2017年09月历史天气为例,把当前页面切换到广州天气页面,如下图:

继续往下滚动页面,直到看到广州历史天气详情,然后点击2017年09月天气 ,进入广州2017年09月天气详情页面,如下图:

注意链接地址的变化:链接中的guangzhou代表地区,201709代表时间。也就是说我们可以通过控制这两个参数,跳转到任意地区和时间的历史天气状况页面。
现在我们看下广州地区201709[http://lishi.tianqi.com/guang...页面的详细信息,滚动页面,可以找到我们想要爬取的数据:

现在,我们已经有了大概的思路:

  1. 先实现如何抓取某一特定页面的数据,例如广州地区2017年09月的历史数据。
  2. 通过控制地区和时间这两个参数,并利用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年的全年天气状况,可以利用上面的函数,通过循环,合并得到你想要的数据。


xiao蜗牛
85 声望20 粉丝

{name: 'Xiao蜗牛',