【问题标题】:XHR Scrape - Request URL not changingXHR Scrape - 请求 URL 不变
【发布时间】:2018-08-29 19:26:17
【问题描述】:

我有一个地址数据库,我正在尝试从 USPS 网络应用程序中抓取 +4 邮政编码数字:https://tools.usps.com/zip-code-lookup.htm?byaddress

我正在使用 Chrome,而该网站使用 XHR。当我输入地址时,我可以很容易地在检查器中找到我的请求的参数...

...以及响应中的数据:


(黄色突出显示的数据是我要抓取的数据)

我读过的关于这个主题的每个教程都说我现在应该“只需获取请求 URL 并将其粘贴到浏览器中以获取 JSON 数据”,并显示一个包含所有参数的 URL。不幸的是,在这种情况下,检查器中的请求 URL 几乎与浏览器 URL 相同,没有包含任何搜索参数。鉴于此,不确定如何继续。

有人可以建议我如何实际获取该 JSON 表吗?如果这很重要,我正在使用 R,尽管我不一定需要帮助解决这个问题的这一部分。

提前致谢。另外,这里是新的 SO 用户,所以在指出本文中任何意外的礼仪违规行为时,请善待。

提前致谢:)

【问题讨论】:

标签: r json ajax web-scraping xmlhttprequest


【解决方案1】:

戳了 robots.txt 和条款和常见问题页面,找不到任何禁止抓取的内容。如果有人这样做,请发表评论,我很乐意删除答案。

有时您不能只获取 URL,尤其是当需要发出 POST 请求时(这里就是这种情况)。这就是curlconverter 出现的地方。右键单击“开发工具”视图中的表格条目,选择“复制为 cURL”,不要在剪贴板上放任何其他内容。然后做:

library(curlconverter)

st <- straighten() 
req <- make_req(st)

st 包含一个带有分解请求组件的列表结构,req[[1]]() 是一个可调用的httr 函数。 然而,如果您在运行 make_req() 行后立即移动到新行并使用剪贴板的 paste 功能,您将获得所述功能的格式化源。在这种情况下,那就是:

httr::VERB(
  verb = "POST", url = "https://tools.usps.com/tools/app/ziplookup/zipByAddress",
  httr::add_headers(
    `User-Agent` = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:63.0) Gecko/20100101 Firefox/63.0",
    Accept = "application/json, text/javascript, */*; q=0.01",
    `Accept-Language` = "en-US,en;q=0.7,fr-BE;q=0.3",
    Referer = "https://tools.usps.com/zip-code-lookup.htm?byaddress",
    `X-Requested-With` = "XMLHttpRequest",
    DNT = "1", Connection = "keep-alive"
  ),
  httr::set_cookies(
    nsc_usps_com = "MTc0LjYyLjE2Ny45Nw==",
    `NSC_uppmt-xbt8-mc` = "ffffffff3b22378c45525d5f4f58455e445a4a4212d3"
  ),
  body = list(
    companyName = "",
    address1 = "1+Main+Street",
    address2 = "", city = "Cambridge",
    state = "MA", zip = ""
  ),
  encode = "form"
)

我们可以从这个自动构建的函数中看出,有 cookie 需要维护,JSON 需要接受,并且——也许——一些其他 HTTP 标头变量需要传递,以及 POST 正文数据。

下一步是对绝对需要的内容进行分类。我没有提示我是如何得出以下内容的,因为您应该做一些工作。为了维护 cookie 状态,我们对源页面进行初始 GET 调用以获取 cookie,只要 R 会话处于活动状态,这些 cookie 就会保持不变。然后,我们传入参数,返回转换后的 JSON:

lookup_zip <- function(address_1, address_2 = "", city = "", 
                       state = "", zip = "", company_name = "") {

  suppressPackageStartupMessages({
    require("httr", quietly = TRUE, warn.conflicts = FALSE)
    require("jsonlite", quietly = TRUE, warn.conflicts = FALSE)
  })

  # prime cookies
  httr::GET(
    url = "https://tools.usps.com/zip-code-lookup.htm",
    httr::user_agent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:63.0) Gecko/20100101 Firefox/63.0")
  ) -> res
  httr::stop_for_status(res)

  httr::POST(
    url = "https://tools.usps.com/tools/app/ziplookup/zipByAddress",
    httr::accept_json(),
    httr::user_agent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:63.0) Gecko/20100101 Firefox/63.0"),
    httr::add_headers(
      Referer = "https://tools.usps.com/zip-code-lookup.htm?byaddress",
      `X-Requested-With` = "XMLHttpRequest"
    ),
    body = list(
      companyName = company_name,
      address1 = address_1,
      address2 = address_2, 
      city = city,
      state = state, 
      zip = zip
    ),
    encode = "form"
  ) -> res

  httr::stop_for_status(res)

  out <- httr::content(res, as = "text", encoding = "UTF-8")

  out <- jsonlite::fromJSON(out)

  out

}

所以,当我们运行时:

lookup_zip("1 Main Street", city = "Cambridge", state = "MA")

## $resultStatus
## [1] "SUCCESS"
## 
## $addressList
##                     addressLine1      city state  zip5 zip4 carrierRoute countyName deliveryPoint checkDigit cmar elot
## 1                      1 MAIN ST CAMBRIDGE    MA 02142 1531         C033  MIDDLESEX            99          3    N 0033
## 2                      1 MAIN ST CAMBRIDGE    MA 02142 1531         C033  MIDDLESEX            99          3    N <NA>
## 3                      1 MAIN ST CAMBRIDGE    MA 02142 1500         C033  MIDDLESEX            01          4    N <NA>
## 4               1 MAIN ST STE 14 CAMBRIDGE    MA 02142 1503         C033  MIDDLESEX            01          1    N <NA>
## 5               1 MAIN ST STE 10 CAMBRIDGE    MA 02142 1504         C033  MIDDLESEX            01          0    N <NA>
## 6               1 MAIN ST STE 24 CAMBRIDGE    MA 02142 1506         C033  MIDDLESEX            01          8    N <NA>
## 7                1 MAIN ST STE 6 CAMBRIDGE    MA 02142 1517         C033  MIDDLESEX            99          9    N <NA>
## 8                1 MAIN ST STE 1 CAMBRIDGE    MA 02142 1517         C033  MIDDLESEX            99          9    N <NA>
## 9               1 MAIN ST STE 11 CAMBRIDGE    MA 02142 1517         C033  MIDDLESEX            99          9    N <NA>
## 10              1 MAIN ST STE 13 CAMBRIDGE    MA 02142 1517         C033  MIDDLESEX            99          9    N <NA>
## 11              1 MAIN ST STE 15 CAMBRIDGE    MA 02142 1517         C033  MIDDLESEX            99          9    N <NA>
## 12               1 MAIN ST STE 8 CAMBRIDGE    MA 02142 1524         C033  MIDDLESEX            01          8    N <NA>
## 13   1 MAIN ST STE (Range 2 - 5) CAMBRIDGE    MA 02142 1599         C033  MIDDLESEX          <NA>       <NA>    N <NA>
## 14  1 MAIN ST STE (Range 7 - 10) CAMBRIDGE    MA 02142 1599         C033  MIDDLESEX          <NA>       <NA>    N <NA>
## 15 1 MAIN ST STE (Range 16 - 24) CAMBRIDGE    MA 02142 1599         C033  MIDDLESEX          <NA>       <NA>    N <NA>
## 16              1 MAIN ST STE 12 CAMBRIDGE    MA 02142 1599         C033  MIDDLESEX            99          9    N <NA>
## 17              1 MAIN ST STE 14 CAMBRIDGE    MA 02142 1599         C033  MIDDLESEX            99          9    N <NA>
##    elotIndicator recordType dpvConfirmation defaultFlag               companyName
## 1              A          H               D           Y                      <NA>
## 2           <NA>       <NA>            <NA>        <NA>                      <NA>
## 3           <NA>       <NA>            <NA>        <NA>                      <NA>
## 4           <NA>       <NA>            <NA>        <NA>     BENCHMARKING PARTNERS
## 5           <NA>       <NA>            <NA>        <NA>              C MARKET INC
## 6           <NA>       <NA>            <NA>        <NA> SIMAT HELLIESEN & EICHNER
## 7           <NA>       <NA>            <NA>        <NA>                      <NA>
## 8           <NA>       <NA>            <NA>        <NA>                      <NA>
## 9           <NA>       <NA>            <NA>        <NA>                      <NA>
## 10          <NA>       <NA>            <NA>        <NA>                      <NA>
## 11          <NA>       <NA>            <NA>        <NA>                      <NA>
## 12          <NA>       <NA>            <NA>        <NA>       NEW ENGLAND PENSION
## 13          <NA>       <NA>            <NA>        <NA>                      <NA>
## 14          <NA>       <NA>            <NA>        <NA>                      <NA>
## 15          <NA>       <NA>            <NA>        <NA>                      <NA>
## 16          <NA>       <NA>            <NA>        <NA>                      CEME
## 17          <NA>       <NA>            <NA>        <NA>                      <NA>

你不应该对以上内容做的事情:

  • 别傻了 #1 :如果您要反复拨打电话,请延迟(即Sys.sleep(5)。您将免费获得此信息,我的税金支持该网站。您是没什么特别的。
  • 别傻了#2:缓存结果,甚至可能在磁盘上。重写函数以使用memoise 包。
  • 别傻了#3:不要出售你正在创建的这个数据库。我会知道你是否这样做(见 #4)
  • 不要成为一个混蛋 #4:尽管 SO 固有地声称其他 w/r/t 答案,但上述代码是 AGPL 许可的,因此您有义务发布您基于它编写的任何商业内容的源代码 (如果这是你的最终意图)。我有每天在互联网上爬行的互联网档案规模系统。我会知道的。

这很可能是一种无辜的学术需求,但 SO 充满了(每天)不道德的内容窃贼提出的抓取问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-27
    • 2012-01-18
    • 2020-10-28
    • 1970-01-01
    • 2015-08-01
    相关资源
    最近更新 更多