当 rvest 无法识别提交按钮时提交 POST 表单

Posted

技术标签:

【中文标题】当 rvest 无法识别提交按钮时提交 POST 表单【英文标题】:Submit POST form when rvest doesn't recognize submit button 【发布时间】:2019-01-31 05:26:44 【问题描述】:

我想提交以下表格(点击链接“Kliknite na ...”后会显示该表格): http://www1.biznet.hr/HgkWeb/do/extlogon

我必须输入一个名为“OIB”的参数,然后单击“Trazi”提交表单。

这是我的代码:

library(httr)
library(rvest)

sess <- html_session("http://www1.biznet.hr/HgkWeb/do/extlogon")
search_page <- sess %>%
  follow_link(1)
form <- html_form(search_page)[[6]]
fill_form <- set_values(form, 'clanica.cla_oib' = '94989605030')
firma_i <- submit_form(search_page, fill_form, submit = 'submit')

最后一行产生错误:

错误:未知的提交名称“提交”。可能的值: clanica.asTextDatumGasenjaTo, clanica.asTextUdr_id

我不明白为什么 rvest 在不包含提交名称或类型的情况下将这两个参数识别为提交按钮。为什么 rvest 不将提交按钮“Trazi”识别为提交参数?总之,如何更改已填写的表单以执行表单?

【问题讨论】:

【参考方案1】:

问题是一些输入错过了type attr,而rvest 没有适当地检查这个。

为了说明问题:

library(httr)
library(rvest)
#> Loading required package: xml2

sess <- html_session("http://www1.biznet.hr/HgkWeb/do/extlogon")
search_page <- sess %>%
  follow_link(1)
#> Navigating to /HgkWeb/do/extlogon;jsessionid=88295900F3F932C85A25BB18F326BE28
form <- html_form(search_page)[[6]]
fill_form <- set_values(form, 'clanica.cla_oib' = '94989605030')

某些字段没有type 属性:

sapply(fill_form$fields, function(x) '['(x, 'type'))
#> $clanica.limitSearchToActiveCompany.type
#> [1] "radio"
#> 
#> $clanica.limitSearchToActiveCompany.type
#> [1] "radio"
#> 
#> $joinBy.useInnerJoin.type
#> [1] "checkbox"
#> 
#> $nazivTvrtke.type
#> [1] "text"
#> 
#> $nazivZapocinjeSaPredanomVrijednoscu.type
#> [1] "checkbox"
#> 
#> $clanica.cla_jmbp.type
#> [1] "text"
#> 
#> $clanica.cla_mbs.type
#> [1] "text"
#> 
#> $clanica.cla_oib.type
#> [1] "text"
#> 
#> $asTextKomoraId.NA
#> NULL
#> 
#> $clanica.asTextOpc_id.NA
#> NULL
#> 
#> $clanica.cla_opcina.type
#> [1] "hidden"
#> 
#> $clanica.asTextNas_id.NA
#> NULL
#> 
#> $clanica.cla_naselje.type
#> [1] "hidden"
#> 
#> $clanica.pos_id.NA
#> NULL
#> 
#> $clanica.postaNaziv.type
#> [1] "hidden"
#> 
#> $clanica.cla_ulica.type
#> [1] "text"
#> 
#> $clanica.asTextDatumUpisaFrom.type
#> [1] "text"
#> 
#> $clanica.asTextDatumUpisaTo.type
#> [1] "text"
#> 
#> $clanica.asTextDatumGasenjaFrom.type
#> [1] "text"
#> 
#> $clanica.asTextDatumGasenjaTo.type
#> [1] "text"
#> 
#> $clanica.asTextUdr_id.NA
#> NULL
#> 
#> $clanica.asTextVel_id.NA
#> NULL
#> 
#> $nkd2007.type
#> [1] "text"
#> 
#> $nkd2007PretrazivanjePoGlavnojDjelatnosti.type
#> [1] "radio"
#> 
#> $nkd2007PretrazivanjePoGlavnojDjelatnosti.type
#> [1] "radio"
#> 
#> $submit.type
#> [1] "submit"
#> 
#> $org.apache.struts.taglib.html.CANCEL.type
#> [1] "submit"
#> 
#> $orderBy.order1.NA
#> NULL
#> 
#> $orderBy.order2.NA
#> NULL
#> 
#> $limit.type
#> [1] "text"
#> 
#> $searchForRowCount.type
#> [1] "checkbox"
#> 
#> $joinBy.gfiGodina.NA
#> NULL
#> 
#> $joinBy.gfiBrojZaposlenihFrom.type
#> [1] "text"
#> 
#> $joinBy.gfiBrojZaposlenihTo.type
#> [1] "text"
#> 
#> $joinBy.gfiUkupniPrihodFrom.type
#> [1] "text"
#> 
#> $joinBy.gfiUkupniPrihodTo.type
#> [1] "text"

这弄乱了内部函数submit_request,特别是其中的Filter()


它被引用了here,并且在this PR 中提出了一个修复,但它自 2016 年 7 月以来一直没有被合并,所以不要屏住呼吸。

PR 中的修复主要检查 type attr 是否存在:

  # form.R, row 280
  is_submit <- function(x) 'type' %in% names(x) &&
                           tolower(x$type) %in% c("submit", "image", "button")

为了快速修复,您可以更改您拥有的数据,用随机类型覆盖 NULL attr:

fill_form$fields <- lapply(fill_form$fields, function(x) 
  null_type = is.null(x$type)
  if (null_type) x$type = 'text'
  x
)


firma_i <- submit_form(search_page, fill_form, submit = 'submit')
firma_i
#> <session> http://www1.biznet.hr/HgkWeb/do/fullSearchPost
#>   Status: 200
#>   Type:   text/html;charset=UTF-8
#>   Size:   4366

由reprex package (v0.2.0) 于 2018 年 8 月 27 日创建。

【讨论】:

以上是关于当 rvest 无法识别提交按钮时提交 POST 表单的主要内容,如果未能解决你的问题,请参考以下文章

后退按钮重新提交表单数据 ($_POST)

当引导验证成功时,如何使用 $.post 提交表单而不进行页面重定向?

提交时无法获取引导下拉列表的值

当所有输入字段在 Hyperscript 中都有效时启用提交按钮?

无法发送“POST”表单,jQuery 不会检测到提交动作

单击提交按钮时无法读取未定义的属性“设置”