使用rvest包刮痧表

时间:2017-12-27 16:31:31

标签: r web-scraping rvest

我对网络抓取非常陌生,我正在探索R中rvest库的潜力。

我正试图通过以下website来填写意大利省份福利表,

install.packages('rvest') 

library('rvest')

url <- 'http://www.ilsole24ore.com/speciali/qvita_2017_dati/home.shtml'

webpage <- read_html(url)

但是我无法识别表格的XPath。

1 个答案:

答案 0 :(得分:3)

即使有以下内容,您还有很多工作要做。 HTML格式很糟糕。

library(rvest)
library(stringi)
library(tidyverse)

read_html("http://www.ilsole24ore.com/speciali/qvita_2017_dati/home.shtml") %>%  # get the main site
  html_node(xpath=".//script[contains(., 'goToDefaultPage')]") %>%               # find the <script> block that dynamically loads the page
  html_text() %>%
  stri_match_first_regex("goToDefaultPage\\('(.*)'\\)") %>%                      # extract the page link
  .[,2] %>% 
  sprintf("http://www.ilsole24ore.com/speciali/qvita_2017_dati/%s", .) %>%       # prepend the URL prefix
  read_html() -> actual_page                                                     # get the dynamic page

tab <- html_nodes(actual_page, xpath=".//table")[[2]]                            # find the actual data table

一旦你做了^^,你就有了一个HTML <table>。这是一个可怕的,可怕的,可怜的形状,并且该网站对于滥用HTML的方式感到羞耻。

继续尝试html_table()。这太糟糕了,它打破了httr

我们需要按行攻击它,并且需要一个辅助函数,以免R代码看起来很糟糕:

`%|0%` <- function(x, y) { if (length(x) == 0) y else x }

^^将帮助我们用空白""填写类似NULL的内容。

现在,我们逐行,提取我们需要的<td>值。由于我不需要这些数据而且需要清理,因此我们稍后会看到这一点,但这并没有得到所有这些;

html_nodes(tab, "tr") %>% 
  map_df(~{
    list(
      posizione = html_text(html_nodes(.x, xpath=".//td[2]"), trim=TRUE) %|0% "",
      diff_pos = html_text(html_nodes(.x, xpath=".//td[5]"), trim=TRUE) %|0% "",
      provincia = html_text(html_nodes(.x, xpath=".//td[8]"), trim=TRUE) %|0% "",
      punti = html_text(html_nodes(.x, xpath=".//td[11]"), trim=TRUE) %|0% "",
      box1 = html_text(html_nodes(.x, xpath=".//td[14]"), trim=TRUE) %|0% "",
      box2 = html_text(html_nodes(.x, xpath=".//td[17]"), trim=TRUE) %|0% "",
      box3 = html_text(html_nodes(.x, xpath=".//td[20]"), trim=TRUE) %|0% ""
    )
  })
## # A tibble: 113 x 7
##     posizione             diff_pos            provincia                 punti  box1  box2  box3
##         <chr>                <chr>                <chr>                 <chr> <chr> <chr> <chr>
##  1            Lavoro e Innovazione                      Giustizia e Sicurezza                  
##  2 Diff. pos.                                                                                  
##  3          1                    3              Belluno                   583                  
##  4          2                   -1                Aosta                   578     9    63    22
##  5          3                    2              Sondrio                   574     4    75     1
##  6          4                    3              Bolzano                   572     2     4     7
##  7          5                   -2               Trento                   567     8    11    15
##  8          6                    4              Trieste                   563     6    10     2
##  9          7                    9 Verbano-Cusio-Ossola                   548    18    73    25
## 10          8                   -6               Milano                   544     1     2    10
## # ... with 103 more rows

正如你所看到的,它错过了一些东西并且在标题中有一些垃圾,但你比以前更进一步。