最近有个培训的小伙伴想要爬取万达官网上所有的万达广场信息。这个可以很容易通过 R 语言实现。
要爬取的网址是:http://www.wandaplazas.com/intro/plaza/

我们可以按 Fn + F12 打开页面审查(我使用的是 Chrome 浏览器):

可以看到我们要爬的内容在 Elements 的这个位置,我们可以右键 copy selector:

然后就可以在 R 语言里面写代码了:
library(tidyverse) library(rvest)
read_html("http://www.wandaplazas.com/intro/plaza/") -> html html %>% html_nodes("#con_one_2") %>% html_text() %>% read_csv(col_names = F) -> df
df
|
然后我们把爬取到的内容整理下:
df %>% dplyr::filter(str_detect(X1, "·") | str_detect(X1, "项目")) %>% mutate(项目信息 = if_else(str_detect(X1, "·"), X1, "")) %>% type_convert() %>% fill(项目信息) %>% dplyr::filter(!str_detect(X1, "·")) %>% select(项目 = 项目信息, 项目信息 = X1) %>% mutate(项目 = str_remove_all(项目, "·")) %>% mutate(项目信息 = if_else(项目 == "渭南临渭万达广场", "项目位于陕西省渭南市高新区,2015年8月开业,商业面积为12.58万平方米。", 项目信息), 项目信息 = if_else(项目 == "南京江宁万达广场", "项目位于江苏省南京市江宁区,2013年12月开业,商业面积为19.57万平方米。", 项目信息), 项目信息 = if_else(项目 == "泉州浦西万达广场", "项目位于福建省泉州市丰泽区,2012年9月开业,商业面积为21.03万平方米。", 项目信息), 项目信息 = if_else(项目 == "衡阳蒸湘万达广场", "项目位于湖南省衡阳市蒸湘区,2017年9月开业,商业面积为12.01万平方米。", 项目信息)) %>% mutate(位置 = str_match(项目信息, "位于(.*),\\d")[,2], 开业时间 = str_match(项目信息, ",(.*)开业")[,2], 商业面积_万平方米 = str_match(项目信息, "商业面积为(.*)万平方米")[,2]) %>% type_convert() %>% mutate(开业时间 = lubridate::ymd(paste0(开业时间,"1日"))) -> df
df
|
这样我们就得到了所有的万达广场信息:
为了在地图上标注这些地点,我们可以使用百度地图解析下经纬度:
library(jsonlite) df %>% mutate(location = map_chr(项目, function(x) { try({ paste0("https://api.map.baidu.com/geocoding/v3/?address=", x, "&output=json&ak=KNfhEZFNPTNL5Gyjm3O81nlE5mURbOhn&ret_coordtype=gcj02ll") %>% fromJSON() -> lst paste0(lst$result$location, collapse = ",") }) })) -> df
df
|
注意这里的 ak=KNfhEZFNPTNL5Gyjm3O81nlE5mURbOhn 是我的百度 ak,大家需要更换成自己的(参考平台上的课程「使用 R 语言进行地理编码:地址解析经纬度、坐标转换 & 根据经纬度判断所处的省市区县」:https://rstata.duanshu.com/#/brief/course/6f8633b486ed49e398c486d0d9f0f59a)
不过这样直接得到的坐标是 GCJ02 坐标,可以使用下面的代码转换成 WGS84 的:
source("坐标转换.R") df %>% separate(location, into = c("经度", "纬度"), sep = ",") %>% mutate(经度 = as.numeric(经度), 纬度 = as.numeric(纬度), value2 = map2_chr(经度, 纬度, GCJ02_WGS84)) %>% select(-contains("度")) %>% separate(value2, into = c("经度", "纬度"), sep = ",") %>% type_convert() -> df df
|
坐标转换.R 文件在附件中。
然后就可以保存了:
df %>% writexl::write_xlsx("万达广场的分布.xlsx")
|
最后我们还可以绘制一副地图展示万达广场的分布:
library(sf) df %>% st_as_sf(coords = c("经度", "纬度"), crs = 4326) -> daloc
library(leaflet) leaflet() %>% addTiles("http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineCommunity/MapServer/tile/{z}/{y}/{x}", attribution = "绘制:微信公众号 RStata") %>% addScaleBar() %>% leafem::addLogo(img = "https://mdniceczx.oss-cn-beijing.aliyuncs.com/image_20201220175301.png", width = 80, height = 80) -> map
mapview::mapview(daloc, map = map, layer.name = "万达广场分布")
|

大家放大这幅地图就可以看到标注的万达广场点和底图上的有所偏差,这是因为这个底图是 GCJ02 的,如果换成 WGS84 的底图,例如 OSM 底图就不会有这种问题了:
mapview::mapview(daloc, layer.name = "万达广场分布")
|

或者不要对坐标进行转换:
daloc %>% st_drop_geometry() %>% mutate(location = map_chr(项目, function(x) { try({ paste0("https://api.map.baidu.com/geocoding/v3/?address=", x, "&output=json&ak=KNfhEZFNPTNL5Gyjm3O81nlE5mURbOhn&ret_coordtype=gcj02ll") %>% fromJSON() -> lst paste0(lst$result$location, collapse = ",") }) })) %>% separate(location, into = c("经度", "纬度"), sep = ",") %>% st_as_sf(coords = c("经度", "纬度"), crs = 4326) -> daloc2 mapview::mapview(daloc2, map = map, layer.name = "万达广场分布")
|

例如:

点击这里跳转到 RStata 短书平台获取附件:使用 R 语言爬取全国所有的万达广场信息
评论