使用 Stata 从文本中提取地址(省市区县乡镇)

在之前的课程「使用 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:

!curl "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=3ac4TeSmH2A0pCg4t1IG7gMl&client_secret=XJQqbFaVfnaed23T1UBRUTUze4flsVjS" -o session.json

insheetjson using session.json, showr flatten

*> Response from server:
*> refresh_token = 25.71051f01c251653d8a8861d6f16cec4f.315360000.2026280353.282335-5724402
*> > 1
*> expires_in = 2592000
*> session_key = 9mzdDAeozGlJ2W8wQkwWme1AymovLxs8Xc3+\/k1LFh05eTk3fN+7lk2\/rzAbNvHeEbubAgz
*> > BhisOlgVHRgYGFn+eHH8I6w==
*> access_token = 24.72e4187635d7134b4c9e3a9b8fbd9b9a.2592000.1713512353.282335-57244021
*> scope = public brain_all_scope brain_nlp_address wise_adapt lebo_resource_base lightser
*> > vice_public hetu_basic lightcms_map_poi kaidian_kaidian ApsMisTest_Test\u6743\u9650 vis-class
*> > ify_flower lpq_\u5f00\u653e cop_helloScope ApsMis_fangdi_permission smartapp_snsapi_base smar
*> > tapp_mapp_dev_manage iop_autocar oauth_tp_app smartapp_smart_game_openapi oauth_sessionkey sm
*> > artapp_swanid_verify smartapp_opensource_openapi smartapp_opensource_recapi fake_face_detect_
*> > \u5f00\u653eScope vis-ocr_\u865a\u62df\u4eba\u7269\u52a9\u7406 idl-video_\u865a\u62df\u4eba\u
*> > 7269\u52a9\u7406 smartapp_component smartapp_search_plugin avatar_video_test b2b_tp_openapi b
*> > 2b_tp_openapi_online smartapp_gov_aladin_to_xcx
*> session_secret = 3639f68c9facac51b976b8d16ac55597

clear
set obs 1
gen str100 access_token = ""
insheetjson access_token using session.json, columns("access_token")

*- 再把它存储到 global 变量里面方便后面调用
global access_token = "`=access_token[1]'"

调用地址识别接口

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

!curl "https://aip.baidubce.com/rpc/2.0/nlp/v1/address?access_token=${access_token}" ///
-H "Content-Type: application/json" ///
-H "Accept: application/json" ///
--data-raw "{\"text\":\"项目名称:金乡县华盛木业有限责任公司土地坐落:金乡县王丕镇康桥村、马楼村(金丰公路南侧)土地使用权人:金乡华盛木业有限责任公司\"}" ///
-o res.json

insheetjson using res.json, showr flatten

*> Response from server:
*> lat = 35.035638
*> detail = 王丕镇康桥村、马楼村(金丰公路南侧)土地使用权人:金乡华盛木业有限责任公司
*> town = 王丕街道
*> phonenum = ""
*> city_code = 370800
*> province = 山东省
*> person = ""
*> lng = 116.358985
*> province_code = 370000
*> text = 项目名称:金乡县华盛木业有限责任公司土地坐落:金乡县王丕镇康桥村、马楼村(金丰公路南侧)土地使用权人:金乡华盛木业有限责任公司
*> county = 金乡县
*> city = 济宁市
*> county_code = 370828
*> town_code = 370828004
*> log_id = 1778460330567968563

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

cap prog drop get_res
prog def get_res
syntax anything(name=text), file(string)
!curl "https://aip.baidubce.com/rpc/2.0/nlp/v1/address?access_token=${access_token}" ///
-H "Content-Type: application/json" ///
-H "Accept: application/json" ///
--data-raw "{\"text\":\"`text'\"}" ///
-o `file'.json
end

使用:

*- 创建文件夹保存结果
cap mkdir "res"
get_res "项目名称:金乡县华盛木业有限责任公司土地坐落:金乡县王丕镇康桥村、马楼村(金丰公路南侧)土地使用权人:金乡华盛木业有限责任公司", file("res/1")

*- 删除这个文件
cap erase res/1.json

这样如果我们需要一次性解析大量文本,就可以先循环获取所有的 json 文件,然后再集中处理:

use data, clear
gen address = "项目名称:" + 项目名称 + "土地坐落:" + 土地坐落 + "土地使用权人:" + 土地使用权人
gen id = _n
save data2, replace
forval i = 1/`=_N' {
if !fileexists("res/`=id[`i']'.json") {
di "`i'"
cap get_res "`=address[`i']'", file("res/`=id[`i']'")
}
}

处理所有的 json 文件:

*- 处理 json 文件
insheetjson using res/54.json, showr flatten
clear
gen str100 lat = ""
gen str100 lng = ""
gen str100 province = ""
gen str100 province_code = ""
gen str100 city = ""
gen str100 city_code = ""
gen str100 county = ""
gen str100 county_code = ""
gen str100 town = ""
gen str100 town_code = ""
gen str100 id = ""
*- 循环所有文件
local files: dir "res" files "*.json"
local n: word count `files'
set obs `n'
local j = 0
foreach i in `files' {
insheetjson lat lng province province_code city ///
city_code county county_code town town_code ///
using "res/`i'", columns("lat" "lng" "province" ///
"province_code" "city" "city_code" "county" ///
"county_code" "town" "town_code") offset(`j')
local j = `j' + 1
replace id = "`i'" in `j'
}

compress

foreach i of varlist _all {
cap format `i' %10s
}

order id
replace id = subinstr(id, ".json", "", .)
destring id lat lng, replace
merge 1:1 id using "data2.dta"
drop _m
save "处理结果", replace

对于没有处理成功的结果,可以考虑手动调整文本后再解析。

更多关于 json 文件处理的内容,感兴趣的小伙伴可以学习这个课程:

Stata 网络数据爬取:JSON篇:https://rstata.duanshu.com/#/brief/course/c6de9fae65df4eeb814d2275545e224d

点击这里跳转到 RStata 短书平台获取附件:使用 Stata 从文本中提取地址(省市区县乡镇)

评论