read_html(url)和read_html(content(GET(url),“ text”)))之间的区别

时间:2019-10-03 12:50:01

标签: r get rvest xml2

我正在寻找一个很好的答案:https://stackoverflow.com/a/58211397/3502164

解决方案的开始包括:

library(httr)
library(xml2)

gr <- GET("https://nzffdms.niwa.co.nz/search")
doc <- read_html(content(gr, "text"))

xml_attr(xml_find_all(doc, ".//input[@name='search[_csrf_token]']"), "value")

在多个请求中输出是恒定的:

"59243d3a2....61f8f73136118f9"

到目前为止,我的默认方式是:

doc <- read_html("https://nzffdms.niwa.co.nz/search")
xml_attr(xml_find_all(doc, ".//input[@name='search[_csrf_token]']"), "value")

结果与上面的输出不同,并且在多个请求中发生了变化。

问题:

两者之间有什么区别

  • read_html(url)
  • read_html(content(GET(url), "text"))

为什么会导致不同的值?为什么只有“ GET”解决方案会在链接的问题中返回csv?

(我希望可以用三个子问题来构成它)。

我尝试过的事情:

深入函数调用的Rabbit漏洞:

read_html
(ms <- methods("read_html"))
getAnywhere(ms[1])
xml2:::read_html
xml2:::read_html.default
#xml2:::read_html.response

read_xml
(ms <- methods("read_xml"))
getAnywhere(ms[1])

但这导致了以下问题:Find the used method for R wrapper functions

想法:

  • 我看不到get请求带有任何标头或Cookies, 可以解释不同的回应。

  • 据我了解,read_htmlread_html(content(GET(.), "text"))都将返回XML / html。

  • 好吧,在这里我不确定是否应该检查,但是因为我没有想法:我检查是否正在进行某种缓存。

代码:

with_verbose(GET("https://nzffdms.niwa.co.nz/search"))
....
<- Expires: Thu, 19 Nov 1981 08:52:00 GMT
<- Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0

->在我看来,缓存可能不是解决方案。

  • 查看help("GET")给出了有关“条件GET”的有趣部分:
  

如果GET方法的语义更改为“条件GET”,   请求消息包括If-Modified-Since,If-Unmodified-Since,   If-Match,If-None-Match或If-Range标头字段。有条件的GET   方法要求仅在   条件标头字段描述的情况。的   有条件的GET方法旨在减少不必要的网络使用   通过允许刷新缓存的实体而无需多个   请求或传输客户端已经拥有的数据。

但是据我对with_verbose()的看法,If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Match, or If-Range都没有设置。

1 个答案:

答案 0 :(得分:4)

区别在于,重复调用httr::GET,句柄在两次调用之间仍然存在。使用xml2::read_html(),每次都建立一个新的连接。

来自httr文档:

  

句柄池用于为相同的方案/主机/端口组合自动重用Curl句柄。这样可以确保http会话能够自动重用,并且Cookie可以在对站点的所有请求中得到维护,而无需用户干预。

在xml2文档中,讨论了传递给read_html()的字符串参数:

  

字符串可以是路径,URL或文字xml。使用base::urlcurl::curl

(如果已安装)将Urls转换为连接

因此,您的答案是read_html(GET(url))就像刷新浏览器,而read_html(url)就像关闭浏览器并打开新的浏览器。服务器在其交付的页面上提供唯一的会话ID。新会话,新ID。您可以通过致电httr::reset_handle(url)来证明这一点:

library(httr)
library(xml2)

# GET the page (note xml2 handles httr responses directly, don't need content("text"))
gr <- GET("https://nzffdms.niwa.co.nz/search")
doc <- read_html(gr)
print(xml_attr(xml_find_all(doc, ".//input[@name='search[_csrf_token]']"), "value"))

# A new GET using the same handle gets exactly the same response
gr <- GET("https://nzffdms.niwa.co.nz/search")
doc <- read_html(gr)
print(xml_attr(xml_find_all(doc, ".//input[@name='search[_csrf_token]']"), "value"))

# Now call GET again after resetting the handle
httr::handle_reset("https://nzffdms.niwa.co.nz/search")
gr <- GET("https://nzffdms.niwa.co.nz/search")
doc <- read_html(gr)
print(xml_attr(xml_find_all(doc, ".//input[@name='search[_csrf_token]']"), "value"))

就我而言,采购上述代码可以使我:

[1] "ecd9be7c75559364a2a5568049c0313f"
[1] "ecd9be7c75559364a2a5568049c0313f"
[1] "d953ce7acc985adbf25eceb89841c713"