XHR Scrape-请求URL不变

时间:2018-08-29 19:26:18

标签: r json ajax web-scraping xmlhttprequest

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

我正在使用Chrome,该站点使用XHR。输入地址后,可以在检查器中轻松找到我的请求参数...

Request parameters

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

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

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

Request URL as shown in inspector

有人可以建议我如何实际获取该JSON表吗?如果重要的话,我正在R中工作,尽管在此问题的那部分我不一定需要帮助。

先谢谢了。另外,这里是新的SO用户,因此,在指出此帖子中的任何礼节性违规行为时,请保持友善。

预先感谢:)

1 个答案:

答案 0 :(得分:0)

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

有时候,您不能只是获取URL,尤其是当要发出POST请求时(在这种情况下)。这就是curlconverter的来源。在“开发人员工具”视图中的表条目上单击鼠标右键,选择“复制为cURL”,并且不要在剪贴板上放置任何其他内容。然后做:

library(curlconverter)

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

st包含具有分解的请求组件的列表结构,并且req[[1]]()是可调用的httr函数。 但是,如果您-立即-在运行make_req()行并将其移至新行并使用剪贴板的粘贴函数之后,您将获得“功能。在这种情况下,就是:

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本身有其他要求,但上面的代码均未提供答案,但上述代码已获得AGPL许可,因此,您有义务发布基于该代码编写的任何商业内容(如果这是您的最终意图)。我有Internet Archive规模系统,每天都在爬网。我会知道的。

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