如何从 URL 中只有月份和年份的网站中的多个表中提取内容 [英] How to extract contents from multiple tables from website with only month and year in URL

查看:33
本文介绍了如何从 URL 中只有月份和年份的网站中的多个表中提取内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我上一个问题的后续:

<块引用>

为什么我会遇到这个错误:Can't recycle 'Date' (size 200) to match '..3' (size 190)?

因为有如下表格(另见这个

这与您描述的排名和统计表的行数始终相同.

This is as follow up to my previous question here:

How to extract contents between div tags with rvest and then bind rows

The page that I am trying to extract the data from between the div tags is from this site:

http://bigbashboard.com/rankings/batsmen

This is a different page to my previous question (although it is still the same site). The key difference is that the dates that appear in the URL are only displayed as year/month like so:

http://bigbashboard.com/rankings/batsmen/2020/10

as opposed to the page in my previous question which appears with year/month/day like this:

http://bigbashboard.com/rankings/bbl/batsmen/2020/01/08

I am still looking to extract the same data from the left hand side of the page which appears between div tags that looks like this:

Batsmen

1 Lokesh Rahul 167
2 Ravija Sanaruwan 150
3 David Warner 143

I also need the data that appears in the table to the right and bind them together so it looks like this, including the date that page has come from like so:

   Date    Rank   Name               Points  Dates                  I   R       HS  Ave     SR      4s  6s  100s  50s
 Oct-20     1     Lokesh Rahul       167     Nov 2018 - Oct 2020    47  1910    132 50.26   141.38  171 76  2     17
 Oct-20     2     Ravija Sanaruwan   150     Jan 2019 - Feb 2020    15  577     103 44.38   165.80  52  36  1     4
 Oct-20     3     David Warner       143     Jan 2019 - Sep 2020    33  1475    100 61.46   138.89  128 39  2     16

I have attempted to use the code offered in the previous post as a solution:

library(rvest)
library(xml2)
library(dplyr)
library(furrr)

batsmen <- function(x) {
  x <- html_nodes(x, "div.cf.rankings-page div div ol li a")
  xml_remove(html_nodes(x, "span.rank small, span[class^='pos'] em"))
  score <- html_text(html_nodes(x, "span.rank"))
  rank <- html_text(html_nodes(x, "span[class^='pos']"), trim = TRUE)
  xml_remove(html_nodes(x, "span"))
  tibble(Rank = rank, Name = html_text(x), Points = score)
}

stats_table <- function(x) {
  as_tibble(html_table(x)[[1L]])
}

read_rankings <- function(url) {
  ymd <- as.Date(paste0(tail(strsplit(url, "/")[[1L]], 3L), collapse = "-"))
  read_html(url) %>% {bind_cols(Date = ymd, batsmen(.), stats_table(.))}
}

mas_url <- "http://bigbashboard.com/rankings/batsmen"

timeline <- 
  read_html(mas_url) %>% 
  html_nodes("div.timeline span a") %>% 
  html_attr("href") %>% 
  url_absolute(mas_url)

# Use parallel processing for speed.
plan(multiprocess)
future_map_dfr(timeline[1:100], read_rankings) # I only scrape a few links for test.

However, this yields an error:

Error in charToDate(x) : 
  character string is not in a standard unambiguous format

I cannot understand why this occurs and how to resolve it. I am assuming it is perhaps because the dates are in a different format.

解决方案

The code below works for all three cases

library(rvest)
library(xml2)
library(dplyr)
library(furrr)

batsmen <- function(x) {
  nms <- html_attr(html_nodes(x, "div.cf > a"), "name")
  x <- html_nodes(x, "div.cf.rankings-page")
  xml_remove(html_nodes(x, "li span.rank small, li span[class^='pos'] em"))
  x <- Map(function(i, nm) {
    i <- html_nodes(i, "li a")
    score <- html_text(html_nodes(i, "span.rank"))
    rank <- html_text(html_nodes(i, "span[class^='pos']"), trim = TRUE)
    xml_remove(html_nodes(i, "span"))
    tibble(Title = nm, Rank = rank, Name = html_text(i), Points = score)
  }, x, nms)
  bind_rows(x)
}

stats_table <- function(x) {
  as_tibble(bind_rows(
    lapply(html_table(x), function(df) setNames(df, make.unique(names(df))))
  ))
}

timeline <- function(mas_url) {
  links <- read_html(mas_url) %>% html_nodes("div.timeline span a")
  out <- links %>% html_attr("href") %>% url_absolute(mas_url)
  setNames(out, html_text(links))
}

read_rankings <- function(url, time) {
  read_html(url) %>% {bind_cols(Date = time, batsmen(.), stats_table(.))}
}

# Use parallel processing for speed.
plan(multiprocess)

Case 1: only men's ranking on that page

# men only
future_imap_dfr(timeline("http://bigbashboard.com/rankings/bbl/batsmen")[1:10], ~read_rankings(.x, .y))

Output

# A tibble: 996 x 15
   Date      Title Rank  Name           Points Dates                         I     R    HS   Ave    SR  `4s`  `6s` `100s` `50s`
   <chr>     <chr> <chr> <chr>          <chr>  <chr>                     <int> <int> <int> <dbl> <dbl> <int> <int>  <int> <int>
 1 8 Feb '20 men   1     Matthew Wade   125    22 Dec 2018 - 30 Jan 2020    23   943   130  44.9  155.    78    36      1     9
 2 8 Feb '20 men   2     Marcus Stoinis 120    21 Dec 2018 - 08 Feb 2020    30  1238   147  53.8  134.   111    39      1    10
 3 8 Feb '20 men   3     D'Arcy Short   116    22 Dec 2018 - 30 Jan 2020    24   994   103  49.7  137.    93    36      1     9
 4 8 Feb '20 men   4     Alex Hales     115    17 Dec 2019 - 06 Feb 2020    17   576    85  38.4  147.    59    23      0     6
 5 8 Feb '20 men   5     Aaron Finch    89     07 Jan 2019 - 27 Jan 2020    17   583   109  36.4  130.    41    24      1     4
 6 8 Feb '20 men   6     Josh Inglis    87     26 Dec 2018 - 26 Jan 2020    18   517    73  28.7  149.    53    19      0     5
 7 8 Feb '20 men   7     Travis Head    87     11 Jan 2019 - 01 Feb 2020    10   291    79  29.1  132.    22    13      0     1
 8 8 Feb '20 men   8     Josh Philippe  84     22 Dec 2018 - 08 Feb 2020    31   791    86  34.4  140.    76    23      0     7
 9 8 Feb '20 men   9     Shaun Marsh    82     24 Jan 2019 - 21 Jan 2020    15   547    96  39.1  128.    45    19      0     4
10 8 Feb '20 men   10    Chris Lynn     78     19 Dec 2018 - 27 Jan 2020    27   772    94  32.2  137.    64    44      0     6
# ... with 986 more rows

Case 2: men's and women's rankings on the same page

# men and women
future_imap_dfr(timeline("http://bigbashboard.com/rankings/batsmen")[1:10], ~read_rankings(.x, .y))

# A tibble: 2,000 x 15
   Date    Title Rank  Name              Points Dates                   I     R    HS   Ave    SR  `4s`  `6s` `100s` `50s`
   <chr>   <chr> <chr> <chr>             <chr>  <chr>               <int> <int> <int> <dbl> <dbl> <int> <int>  <int> <int>
 1 Oct '20 men   1     Lokesh Rahul      167    Nov 2018 - Oct 2020    47  1910   132  50.3  141.   171    76      2    17
 2 Oct '20 men   2     Ravija Sandaruwan 150    Jan 2019 - Feb 2020    15   577   103  44.4  166.    52    36      1     4
 3 Oct '20 men   3     David Warner      143    Jan 2019 - Sep 2020    33  1475   100  61.5  139.   128    39      2    16
 4 Oct '20 men   4     Kamran Khan       135    Jan 2019 - Feb 2020    21   630    88  31.5  135.    50    39      0     5
 5 Oct '20 men   5     Devdutt Padikkal  135    Nov 2019 - Sep 2020    15   691   122  57.6  167.    72    35      1     7
 6 Oct '20 men   6     Devon Conway      121    Dec 2018 - Jan 2020    20   906   105  56.6  145.   113    19      2     5
 7 Oct '20 men   7     Jos Buttler       121    Oct 2018 - Oct 2020    23   817    89  37.1  145.    93    32      0     8
 8 Oct '20 men   8     Virat Kohli       119    Nov 2018 - Sep 2020    35  1174   100  40.5  141.    90    43      1     8
 9 Oct '20 men   9     Kevin O'Brien     119    Oct 2018 - Sep 2020    38  1145   124  31.0  158.   107    59      1     5
10 Oct '20 men   10    Eoin Morgan       118    Oct 2018 - Oct 2020    34  1008    91  38.8  165.    69    66      0     8
# ... with 1,990 more rows

Case 3: all rounders

# all-rounders
future_imap_dfr(timeline("http://bigbashboard.com/rankings/bbl/all-rounders")[1:10], ~read_rankings(.x, .y))

# A tibble: 547 x 13
   Date      Title Rank  Name             Points Dates                         M     R   Ave    SR     W  Econ Ave.1
   <chr>     <chr> <chr> <chr>            <chr>  <chr>                     <int> <int> <dbl> <dbl> <int> <dbl> <dbl>
 1 8 Feb '20 men   1     D'Arcy Short     70     22 Dec 2018 - 30 Jan 2020    24   994  49.7  137.    16  8.61  29.1
 2 8 Feb '20 men   2     Travis Head      49     11 Jan 2019 - 01 Feb 2020    11   291  29.1  132.     4  8.08  24.2
 3 8 Feb '20 men   3     Mohammad Nabi    40     20 Dec 2018 - 27 Jan 2020    20   388  29.8  129.    13  7.9   30.4
 4 8 Feb '20 men   4     Chris Morris     38     21 Dec 2019 - 06 Feb 2020    15   112  12.4  147.    22  8.01  19.4
 5 8 Feb '20 men   5     Glenn Maxwell    37     21 Dec 2018 - 08 Feb 2020    30   729  36.4  146.    13  7.36  31.2
 6 8 Feb '20 men   6     Daniel Sams      35     21 Dec 2018 - 06 Feb 2020    31   230   9.2  119.    45  8.19  17.3
 7 8 Feb '20 men   7     Ben Cutting      33     19 Dec 2018 - 27 Jan 2020    28   466  24.5  137.    23  8.92  27.5
 8 8 Feb '20 men   8     Mitchell Marsh   28     20 Dec 2018 - 26 Jan 2020    21   504  31.5  132.     6  9.56  43  
 9 8 Feb '20 men   9     Daniel Christian 27     20 Dec 2018 - 27 Jan 2020    30   382  21.2  124.    20  8.02  27.2
10 8 Feb '20 men   10    Rashid Khan      26     19 Dec 2018 - 01 Feb 2020    29   217  14.5  158.    38  6.65  19.5
# ... with 537 more rows

Q&A

How does the date work?

The new code scrapes both link and date from the same timeline on the website. Link is that href attribute; date is the text. See that timeline function. In this way, I avoid using URL to get the date.

Why did I encounter this Error: Can't recycle 'Date' (size 200) to match '..3' (size 190)?

Because there are tables as follows (also see this link)

which differs from your description that the ranking and stats tables always have the same number of rows.

这篇关于如何从 URL 中只有月份和年份的网站中的多个表中提取内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆