奇怪的是,他们用于出口查找的主站点和提供者都不会阻止C或REP进行搜索。 ¯\_(ツ)_/¯
你真的应该熟悉的浏览器开发者工具,你就已经能够看出,主站点发出HTTP POST
请求查找网站的VS要求GET
浏览器通常让那read_html()
做。这里有您需要做什么才能获得成功请求(我们会选择一个邮政编码近十岁上下的你):
library(httr)
library(rvest)
POST(
url = "http://www.nearestoutlet.com/cgi-bin/smi/findsmi.pl",
body = list(zipcode = "48127"),
encode = "form"
) -> res
res
是httr
response
对象和一个会通常只是做:
content(res, as="parsed")
得到一个解析对象准备XML/HTML解析。但是,有奇怪的编码问题(至少对我来说),在该网站上迫使我们必须做的:
content(res, as="raw") %>% read_html() -> pg
您应该cat(as.character(pg))
看看HTML是如何丑陋。它是嵌套表格,但不是一个好方法。您看到的条目全部为<tr>
元素,没有<table>
中断。值得庆幸的是?在这些<tr>
元素的每一个中只有单个的<td>
元素。因此,我们可以通过瞄准正确的<table>
抓住他们所有一举:
rows <- html_nodes(pg, "table[width='300'] > tr > td")
rows
## {xml_nodeset (60)}
## [1] <td width="300" height="19" bgcolor="#8B0101"><p align="left"><font face="Tahoma" color="#FFFFFF" style="font-size: 11px"><b>O\u0092REILLY AUTO PARTS</b></fo ...
## [2] <td width="300" height="2"><font face="Tahoma" style="font-size: 11px">6938 NORTH TELEGRAPH ROAD</font></td>
## [3] <td width="300" height="2"><font face="Tahoma" style="font-size: 11px">Dearborn Heights, MI 48127</font></td>
## [4] <td width="300" height="2"><font face="Tahoma" style="font-size: 11px">(313) 792-9134</font></td>
## [5] <td width="300" height="2"><font face="Tahoma" style="font-size: 11px"><a href="#" onclick="window.open('http://maps.google.com/maps?q=6938+NORTH+TELEGRAPH+R ...
## [6] <td width="300" height="6"></td>
## [7] <td width="300" height="19" bgcolor="#8B0101"><p align="left"><font face="Tahoma" color="#FFFFFF" style="font-size: 11px"><b>Advance Auto Parts</b></font></p ...
## [8] <td width="300" height="2"><font face="Tahoma" style="font-size: 11px">8120 North Telegraph Road</font></td>
## [9] <td width="300" height="2"><font face="Tahoma" style="font-size: 11px">Dearborn Heights, MI 48127</font></td>
## [10] <td width="300" height="2"><font face="Tahoma" style="font-size: 11px">(313) 528-4920</font></td>
## [11] <td width="300" height="2"><font face="Tahoma" style="font-size: 11px"><a href="#" onclick="window.open('http://maps.google.com/maps?q=8120+North+Telegraph+R ...
## [12] <td width="300" height="6"></td>
## [13] <td width="300" height="19" bgcolor="#8B0101"><p align="left"><font face="Tahoma" color="#FFFFFF" style="font-size: 11px"><b>Pep Boys</b></font></p></td>
## [14] <td width="300" height="2"><font face="Tahoma" style="font-size: 11px">8955 TELEGRAPH RD</font></td>
## [15] <td width="300" height="2"><font face="Tahoma" style="font-size: 11px">Redford, MI 48239</font></td>
## [16] <td width="300" height="2"><font face="Tahoma" style="font-size: 11px">(313) 532-5750</font></td>
## [17] <td width="300" height="2"><font face="Tahoma" style="font-size: 11px"><a href="#" onclick="window.open('http://maps.google.com/maps?q=8955+TELEGRAPH+RD+Redf ...
## [18] <td width="300" height="6"></td>
## [19] <td width="300" height="19" bgcolor="#8B0101"><p align="left"><font face="Tahoma" color="#FFFFFF" style="font-size: 11px"><b>O\u0092REILLY AUTO PARTS</b></fo ...
## [20] <td width="300" height="2"><font face="Tahoma" style="font-size: 11px">27207 PLYMOUTH ROAD</font></td>
## ...
有许多接近一个可能需要做一个数据帧的是混乱的。一个简单的方法就是使用商店标题具有设置背景色的事实,而其他人则不会。这使得代码有点脆弱,但是通过测试背景颜色的存在,我们可以帮助它变得更加脆弱。为什么我们甚至需要这样做?那么,我们需要标记记录的开始和结束,一个简单的方法就是使用这样一个事实,即我们可以知道cumsum()
是一个逻辑向量FALSE
== 0.为什么这很重要?我们可以创建一个隐含的分组列这样:
data_frame(
record = !is.na(html_attr(rows, "bgcolor")),
text = html_text(rows, trim=TRUE)
) %>%
mutate(record = cumsum(record)) -> xdf
#3 # A tibble: 60 x 2
#3 record text
#3 <int> <chr>
#3 1 1 "O\u0092REILLY AUTO PARTS"
#3 2 1 6938 NORTH TELEGRAPH ROAD
#3 3 1 Dearborn Heights, MI 48127
#3 4 1 (313) 792-9134
#3 5 1 0 miles away
#3 6 1
#3 7 2 Advance Auto Parts
#3 8 2 8120 North Telegraph Road
#3 9 2 Dearborn Heights, MI 48127
#3 10 2 (313) 528-4920
#3 # ... with 50 more rows
现在,我们需要与filter()
删除空行,并做一些改写(munging)获取数据到一个像样的形式制作的数据帧。这是超级脆弱代码,因为这个特定的片段可以处理丢失的电话号码数据,但这就是它。如果有第二个地址线,你需要修改这个方法,或者使用不同的方法:
filter(xdf, text != "") %>%
group_by(record) %>%
summarise(x = paste0(text, collapse="|")) %>%
separate(x, c("store", "address1", "city_state_zip", "phone_and_or_distance"), sep="\\|", extra="merge")
## # A tibble: 10 x 5
## record store address1 city_state_zip phone_and_or_distance
## * <int> <chr> <chr> <chr> <chr>
## 1 1 "O\u0092REILLY AUTO PARTS" 6938 NORTH TELEGRAPH ROAD Dearborn Heights, MI 48127 (313) 792-9134|0 miles away
## 2 2 Advance Auto Parts 8120 North Telegraph Road Dearborn Heights, MI 48127 (313) 528-4920|0 miles away
## 3 3 Pep Boys 8955 TELEGRAPH RD Redford, MI 48239 (313) 532-5750|2 miles away
## 4 4 "O\u0092REILLY AUTO PARTS" 27207 PLYMOUTH ROAD Redford, MI 48239 (313) 937-1787|2 miles away
## 5 5 "O\u0092REILLY AUTO PARTS" 14975 TELEGRAPH ROAD Redford, MI 48239 (313) 538-3584|2 miles away
## 6 6 AutoZone 24250 FIVE MILE Redford, MI 48239 (313) 527-6877|2 miles away
## 7 7 "O\u0092REILLY AUTO PARTS" 5940 MIDDLEBELT RD Garden City, MI 48135 (734) 525-1607|3 miles away
## 8 8 AutoZone 6228 MIDDLEBELT RD Garden City, MI 48135 (734) 513-2233|3 miles away
## 9 9 Advance Auto Parts 3845 S Telegraph Rd Dearborn, MI 48124 (313) 274-6549|3 miles away
## 10 10 "O\u0092REILLY AUTO PARTS" 27565 MICHIGAN AVENUE Inkster, MI 48141 (313) 724-8544|3 miles away
万一这个过程是不明显的,我们:
- 组行通过我们刚创建的
record
列
- 斯马什所有文本合并为一个字符串,将每个部分与
|
的
- 分离出所有单个比特分开
这可能有助于解释脆弱性。当然,你只想要“如何到达内容”部分,但希望这会为你节省更多时间。
哇!对于所有步骤来说,这是多么美妙的解释您还教会了我一种更有效的处理嵌套数据的新方法。我一直在处理这样的数据结构,而这只是清理时间的一小部分。我是否需要从一个循环中打印值,从一系列邮政编码中运行此问题?通常我只会用列表命名一个对象。 – Turbogoon
如果你可以在一个新问题中做出一个可重复的例子,它会使我和其他人都能够提供帮助。我很高兴,这解决了你的一些问题,寿。 – hrbrmstr
它做的比这更多。数据困难巨大。我在这里发布了一个新问题https://stackoverflow.com/questions/46759058/how-to-pass-multiple-values-in-a-rvest-submission-form再次感谢您的帮助。我提高了但是新的我不认为它做了很多。 – Turbogoon