如何在没有按钮参数的 Rvest 包中提交登录表单
Posted
技术标签:
【中文标题】如何在没有按钮参数的 Rvest 包中提交登录表单【英文标题】:How to submit login form in Rvest package w/o button argument 【发布时间】:2016-04-22 05:11:46 【问题描述】:我正在尝试使用 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("电子邮件","密码")
我也不知道如何引用提交按钮,所以我尝试了: submit_form(帐号,登录)
提交表单函数的错误是: 名称错误(提交)[[1]]:下标超出范围
任何关于如何解决这个问题的想法都值得赞赏。 谢谢
【问题讨论】:
【参考方案1】:目前,此问题与rvest
包中打开的issue #159 相同,这会导致表单中并非所有字段都具有type
值的问题。此购买可能会在未来的版本中修复。
但是,我们可以通过猴子修补底层函数 rvest:::submit_request
来解决此问题。
核心问题是辅助函数is_submit
。最初,它是这样定义的:
is_submit <- function(x) tolower(x$type) %in% c("submit",
"image", "button")
尽管如此合乎逻辑,但它在两种情况下都会失败:
-
没有
type
元素。
type
元素是NULL
。
这两种情况都发生在美联航登录表单上。我们可以通过在函数中添加两个检查来解决这个问题。
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
包(如果没有,请通过install.packages("R.utils")
安装)。
library(R.utils)
reassignInPackage("submit_request", "rvest", custom.submit_request)
从那里,我们可以发出我们自己的请求。
account <- account %>%
submit_form(login, "ctl00$ContentInfo$SignInSecure")
这行得通!
(好吧,“works”是用词不当。由于 United 采用更严格的身份验证要求 - 包括已知浏览器 - 这导致 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 包中提交登录表单的主要内容,如果未能解决你的问题,请参考以下文章
高分求教:如何实现java web 按钮点击弹出登陆界面,并登陆
如何将帐户信息放入 Facebook 登录表单并单击 Web 浏览器控件中的提交按钮?