오기 - 버튼 인수가없는 Rvest 패키지의 로그인 양식 제출 방법



r 웹 데이터 불러 오기 (1)

나는 rvest 패키지에서 html_session () & html_form ()을 사용하여 인증을 요구하는 웹 페이지를 긁어 내려고한다. 예를 들어 Hadley Wickham이 제공 한 것으로 알았지 만 내 경우에 맞춤 설정할 수 없습니다.

united <- html_session("http://www.united.com/")
account <- united %>% follow_link("Account")
login <- account %>%
         html_nodes("form") %>%
         extract2(1) %>%
         html_form() %>%
         set_values(
                `ctl00$ContentInfo$SignIn$onepass$txtField` = "GY797363",
                `ctl00$ContentInfo$SignIn$password$txtPassword` = password)
account <- account %>% 
submit_form(login, "ctl00$ContentInfo$SignInSecure")

필자의 경우 양식에 설정할 값을 찾을 수 없으므로 사용자에게주고 직접 전달하려고합니다. set_values ​​( "email", "password")

또한 제출 버튼을 참조하는 방법을 모르므로 시도했습니다. submit_form (account, login)

submit_form 함수에 대한 오류는 다음과 같습니다. 이름 (submits) [[1]]의 오류 : 범위를 벗어나는 subscript

이 문제를 해결하는 방법에 대한 아이디어는 높이 평가됩니다. 고맙습니다


현재이 문제는 양식의 모든 필드에 type 값이없는 문제를 일으키는 rvest 패키지의 rvest 문제 # 159 와 동일합니다. 이 구매는 다음 릴리스에서 수정 될 수 있습니다.

그러나 원숭이가 기본 함수 rvest:::submit_request 패치를 적용하여 문제를 해결할 수 있습니다.

핵심 문제는 도우미 함수 is_submit 입니다. 처음에는 다음과 같이 정의됩니다.

is_submit <- function(x) tolower(x$type) %in% c("submit", 
        "image", "button")

그러나 이것이 논리적 인 것처럼 두 가지 시나리오에서 실패합니다.

  1. type 요소가 없습니다.
  2. type 요소는 NULL 입니다.

이 두 가지 모두 United 로그인 양식에서 발생합니다. 함수 내부에 두 개의 검사를 추가하여이를 해결할 수 있습니다.

custom.submit_request <- function (form, submit = NULL) 
{
  is_submit <- function(x) {
    if (!exists("type", x) | is.null(x$type)){
      return(F);
    }
    tolower(x$type) %in% c("submit", "image", "button")
  } 
  submits <- Filter(is_submit, form$fields)
  if (length(submits) == 0) {
    stop("Could not find possible submission target.", call. = FALSE)
  }
  if (is.null(submit)) {
    submit <- names(submits)[[1]]
    message("Submitting with '", submit, "'")
  }
  if (!(submit %in% names(submits))) {
    stop("Unknown submission name '", submit, "'.\n", "Possible values: ", 
         paste0(names(submits), collapse = ", "), call. = FALSE)
  }
  other_submits <- setdiff(names(submits), submit)
  method <- form$method
  if (!(method %in% c("POST", "GET"))) {
    warning("Invalid method (", method, "), defaulting to GET", 
            call. = FALSE)
    method <- "GET"
  }
  url <- form$url
  fields <- form$fields
  fields <- Filter(function(x) length(x$value) > 0, fields)
  fields <- fields[setdiff(names(fields), other_submits)]
  values <- pluck(fields, "value")
  names(values) <- names(fields)
  list(method = method, encode = form$enctype, url = url, values = values)
}

원숭이 패치를 사용하려면 R.utils 패키지를 사용해야합니다 (설치 패키지가 R.utils install.packages("R.utils") 를 통해 설치 install.packages("R.utils") ).

library(R.utils)

reassignInPackage("submit_request", "rvest", custom.submit_request)

거기에서 우리는 우리 자신의 요청을 할 수 있습니다.

account <- account %>% 
     submit_form(login, "ctl00$ContentInfo$SignInSecure")

그리고 그 작품!

(글쎄, "작품"은 잘못된 명칭이다. 유나이티드가 알려진 브라우저를 포함하여보다 공격적인 인증 요구 사항을 사용하고 있기 때문에 301 Unauthorized 가 발생하지만 오류가 수정된다.

완전히 재현 할 수있는 예제에는 다음과 같은 몇 가지 사소한 코드 변경 사항이 있습니다.

library(magrittr)
library(rvest)

url <- "https://www.united.com/web/en-US/apps/account/account.aspx"
account <- html_session(url)
login <- account %>%
  html_nodes("form") %>%
  extract2(1) %>%
  html_form() %>%
  set_values(
    `ctl00$ContentInfo$SignIn$onepass$txtField` = "USER",
    `ctl00$ContentInfo$SignIn$password$txtPassword` = "PASS")
account <- account %>% 
  submit_form(login, "ctl00$ContentInfo$SignInSecure")




rvest