Ничего не возвращается, когда я пытаюсь очистить транзакции mlb.com, используя rvest - PullRequest
0 голосов
/ 24 мая 2019

Я безуспешно пытался почистить страницу транзакций mlb (http://mlb.mlb.com/mlb/transactions/index.jsp#month=5&year=2019) для соответствующей даты и текста каждой данной транзакции. Используя rvest и гаджет селектора, я написал краткую функцию, которая должна дать мнетаблица отображалась полностью с первого доступного периода с 2001 по март 2019 года.

Я просто получаю эту серию ошибок, и ничего не происходит.

Вот мой код для очистки данныхс данного веб-сайта.

library(tidyverse)
library(rvest)


# breaking the URL into the start and end for easy pasting to fit timespan
url_start = "http://mlb.mlb.com/mlb/transactions/index.jsp#month="
url_end = "&year="

# function which scrapes data

mlb_transactions = function(month, year){

  url = paste0(url_start, month, url_end, year)

  payload = read_html(url) %>%
              html_nodes("td") %>%
                html_table() %>%
                  as.data.frame()

  payload

}

# function run on appropriate dates

mlb_transactions(month = 1:12, year = 2001:2019)

вот ошибки, которые я получаю

 Show Traceback

 Rerun with Debug
 Error in doc_parse_file(con, encoding = encoding, as_html = as_html, options = options) : 
  Expecting a single string value: [type=character; extent=19]. 

, а вот обратная трассировка

12.
stop(structure(list(message = "Expecting a single string value: [type=character; extent=19].", 
    call = doc_parse_file(con, encoding = encoding, as_html = as_html, 
        options = options), cppstack = NULL), class = c("Rcpp::not_compatible", 
"C++Error", "error", "condition"))) 
11.
doc_parse_file(con, encoding = encoding, as_html = as_html, options = options) 
10.
read_xml.character(x, encoding = encoding, ..., as_html = TRUE, 
    options = options) 
9.
read_xml(x, encoding = encoding, ..., as_html = TRUE, options = options) 
8.
withCallingHandlers(expr, warning = function(w) invokeRestart("muffleWarning")) 
7.
suppressWarnings(read_xml(x, encoding = encoding, ..., as_html = TRUE, 
    options = options)) 
6.
read_html.default(url) 
5.
read_html(url) 
4.
eval(lhs, parent, parent) 
3.
eval(lhs, parent, parent) 
2.
read_html(url) %>% html_nodes("td") %>% html_table() %>% as.data.frame() 
1.
mlb_transactions(month = 1:12, year = 2001:2019) 

Последнее замечание заключается в том, чтоу меня такой план, хотя я пока не знаю, как это сделать, потому что в таблицах транзакций не у каждой транзакции есть дата, оставленная непосредственно перед ней, но есть предполагаемый интервал дат, который я мог бы сделать так, как только будет загружен каждый пустой столбец даты.с информацией о столбце непосредственно над ним, если он заполнен, и это запускает своего рода цикл или есть лучший способ загрузить даты с самого начала?

Ответы [ 2 ]

2 голосов
/ 25 мая 2019

Вот альтернатива R - похожая на решение @ QHarr.Следующая функция get_data принимает year в качестве аргумента и извлекает данные для year;year+1 в качестве даты начала и окончания

get_data <- function (year) {
  root_url <- 'http://lookup-service-prod.mlb.com'
  params_dates <- sprintf('start_date=%s0101&end_date=%s1231', year, year+1)
  params <- paste('/json/named.transaction_all.bam?&sport_code=%27mlb%27', params_dates, sep = '&')
  js <- jsonlite::fromJSON(paste0(root_url, params))
  return (js)
}
get_processed_data <- function (year) get_data(year=year)$transaction_all$queryResults$row

Выход js имеет класс list, и данные сохраняютсяв $transaction_all$queryResults$row.

Наконец, тот же цикл, что и в другом решении, распечатывает количество строк выходного сигнала

for (year in seq(2001, 2018, 2)) print(nrow(get_data(year)$transaction_all$queryResults$row))
# [1] 163
# [1] 153
# [1] 277
# [1] 306
# [1] 16362
# [1] 19986
# [1] 20960
# [1] 23352
# [1] 24732
2 голосов
/ 24 мая 2019

Псевдокод (не зависит от языка):

Существует альтернативная конструкция URL, которая возвращает json через строку запроса.Строка запроса имеет дату начала и окончания.

http://lookup -service-prod.mlb.com / json / named.transaction_all.bam? Start_date = 20010101 & end_date = 20031231 & sport_code =% 27mlb% 27

Из тестирования с Python (так что пробег R может отличаться - я надеюсь добавить пример R позже) вы можете отправлять запросы на * 2 года за раз и получать ответ json со строками данных.в. * Это были более надежные временные рамки.

Вы можете построить это в цикле с 2001 по 2018 с шагом 2, то есть

интервалы

['2001-2003', '2004-2006', '2007-2009' ,'2010-2012', '2013-2015', '2016-2018]

Затем проанализируйте ответ json для данных, представляющих интерес.Пример ответа json здесь .

Пример строки в json:

{"trans_date_cd":"D","from_team_id":"","orig_asset":"Player","final_asset_type":"","player":"Rafael Roque","resolution_cd":"FIN","final_asset":"","name_display_first_last":"Rafael Roque","type_cd":"REL","name_sort":"ROQUE, RAFAEL","resolution_date":"2001-03-14T00:00:00","conditional_sw":"","team":"Milwaukee Brewers","type":"Released","name_display_last_first":"Roque, Rafael","transaction_id":"94126","trans_date":"2001-03-14T00:00:00","effective_date":"2001-03-14T00:00:00","player_id":"136305","orig_asset_type":"PL","from_team":"","team_id":"158","note":"Milwaukee Brewers released LHP Rafael Roque."}

Примечание:

Немассовое использование Материалов разрешено, но массовое использование требует предварительного согласия.


Пример Python:

import requests

for year in range(2001, 2018, 2):       
    r = requests.get('http://lookup-service-prod.mlb.com/json/named.transaction_all.bam?start_date={0}0101&end_date={1}1231&sport_code=%27mlb%27'.format(year,year + 1)).json()
    print(len(r['transaction_all']['queryResults']['row'])) # just to demonstrate response content

This

len(r['transaction_all']['queryResults']['row'])

дает количество строк / транзакций данных на запрос (2 года)

Это дает количество транзакций:

[163, 153, 277, 306, 16362, 19986, 20960, 23352, 24732]
...