使用 R 语言从文本中提取地址

在之前的课程「使用 R 语言调用百度大脑自然语言处理接口进行文本情感倾向分析」中我们介绍了百度大脑接口的使用。最近有个小伙伴遇到了这样一个问题,他想要从例如下面的文本中提取保护区所在的省市区县信息:

项目名称:金乡县华盛木业有限责任公司土地坐落:金乡县王丕镇康桥村、马楼村(金丰公路南侧)土地使用权人:金乡华盛木业有限责任公司

今天我们将会讲解如何使用百度大脑的地址识别接口来解决这个问题。

百度大脑的地址识别接口的介绍文档在这里:https://ai.baidu.com/ai-doc/NLP/vk6z52h5n

创建应用

首先我们需要在控制台找到自然语言处理:https://console.bce.baidu.com/ai/#/ai/nlp/overview/index,点击开通:

开头可以点击“免费尝鲜”领取免费额度,每个账号 5000 次,用完之后也可以再点击开通,费用是 0.0025元/次,例如 10 万次请求的费用就是 250 元。勉强还可以接受。

然后创建一个应用,创建后就可以看到这个应用了:

API Key 和 Secret Key 就是我们需要在代码中调用的东西,大家需要替换成自己的。

获取 accsee_token

根据情感倾向分析接口的文档介绍,我们需要先根据 API Key 和 Secret Key 请求获取 access_token:

library(tidyverse)
library(jsonlite)

haven::read_dta("data.dta") -> df

# 合并包含地址的一些信息:
df %>%
mutate(address = paste0("项目名称:", 项目名称,
"土地坐落:", 土地坐落,
"土地使用权人:", 土地使用权人)) -> df

# 自然语言处理控制台:https://console.bce.baidu.com/ai/#/ai/nlp/overview/index
library(httr)

fromJSON("https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=3ac4TeSmH2A0pCg4t1IG7gMl&client_secret=XJQqbFaVfnaed23T1UBRUTUze4flsVjS") -> lst

lst$access_token

调用地址识别接口

然后就可以使用这个 access_token 调用地址识别接口了:

POST(paste0("https://aip.baidubce.com/rpc/2.0/nlp/v1/address?access_token=", lst$access_token),
httr::add_headers(.headers = c(
'Content-Type' = 'application/json',
'Accept' = 'application/json'
)),
body = '{"text":"项目名称:金乡县华盛木业有限责任公司土地坐落:金乡县王丕镇康桥村、马楼村(金丰公路南侧)土地使用权人:金乡华盛木业有限责任公司"}') -> res

content(res) %>%
listviewer::jsonedit()

content(res) -> reslst

reslst %>%
as_tibble()

为了更方便使用,我们可以编写一个函数:

bd_add <- function(x, access_token = lst$access_token) {
httr::POST(paste0("https://aip.baidubce.com/rpc/2.0/nlp/v1/address?access_token=", lst$access_token),
httr::add_headers(.headers = c(
'Content-Type' = 'application/json',
'Accept' = 'application/json'
)),
body = paste0('{"text":"', x, '"}')) %>%
content() %>%
as_tibble()
}

使用:

bd_add(df$address[2])
bd_add(df$address[40])

然后就可以在数据框中使用了:

df %>%
slice_sample(n = 10) %>%
mutate(res = map(address, bd_add)) -> df2

df2 %>%
unnest(res) %>%
select(address, lat, lng, province, city, county)

如果要解析的观测值较多,建议每解析一次保存一行:

dir.create("res")
for (i in 1:nrow(df)) {
if (!file.exists(paste0("res/", i, ".rds"))) {
print(i)
df %>%
slice(i) %>%
mutate(res = map(address, bd_add)) %>%
write_rds(paste0("res/", i, ".rds"))
}
}

然后就可以合并结果了,对于解析失败的也可以单独再重新运行:

lapply(fs::dir_ls("res"), read_rds) %>%
bind_rows() -> dfall

dfall %>%
unnest(res) %>%
select(address, lat, lng, province, city, county)

点击这里跳转到 RStata 短书平台获取附件:使用 R 语言从文本中提取地址

评论