这代码是自己根据官网的demo结合业务需求修改之后的版本
具体api请参考官方文档实现,只需要根据api设置参数即可
# -- coding: utf-8 --
import time
import random
import hmac
import base64
import copy
import urllib.parse
import requests
import logging
# 应用id
accesskey_id = '**********'
# 应用key
accesskey_secret = '**********'
# 域名
internet_host = 'opensearch-cn-shanghai.aliyuncs.com'
# 应用名
land_name = 'lansi_system_land'
buildings_name = 'lansi_system_build'
logger = logging.getLogger('open_search')
class V3Api:
# 定义变量
URI_PREFIX = '/v3/openapi/apps/'
OS_PREFIX = 'OPENSEARCH'
VERB = 'GET'
def __init__(self, address='', port=''):
self.address = address
self.port = port
def runQuery(self,
app_name=None,
access_key=None,
secret=None,
http_header={},
http_params={}):
query, header = self.buildQuery(app_name=app_name,
access_key=access_key,
secret=secret,
http_header=http_header,
http_params=http_params)
url = f'http://{self.address}{query}'
response = requests.request(self.VERB, url=url, headers=header)
return response.status_code, response.headers, response.json()
def buildQuery(self,
app_name=None,
access_key=None,
secret=None,
http_header={},
http_params={}):
uri = self.URI_PREFIX
if app_name is not None:
uri += app_name
uri += '/search'
param = []
for key, value in http_params.items():
param.append(urllib.parse.quote(key) + '=' + urllib.parse.quote(value))
query = ('&'.join(param))
request_header = self.buildRequestHeader(uri=uri,
access_key=access_key,
secret=secret,
http_params=http_params,
http_header=http_header)
return uri + '?' + query, request_header
# 此处为签名代码实现
def buildAuthorization(self, uri, access_key, secret, http_params, request_header):
canonicalized = self.VERB + '\n' \
+ self.__getHeader(request_header, 'Content-MD5', '') + '\n' \
+ self.__getHeader(request_header, 'Content-Type', '') + '\n' \
+ self.__getHeader(request_header, 'Date', '') + '\n' \
+ self.__canonicalizedHeaders(request_header) \
+ self.__canonicalizedResource(uri, http_params)
signature_hmac = hmac.new(secret.encode('utf-8'), canonicalized.encode('utf-8'), 'sha1')
signature = base64.b64encode(signature_hmac.digest())
return '%s %s%s%s' % (self.OS_PREFIX, access_key, ':', signature.decode('utf-8'))
def __getHeader(self, header, key, default_value=None):
if key in header and header[key] is not None:
return header[key]
return default_value
def __canonicalizedResource(self, uri, http_params):
canonicalized = urllib.parse.quote(uri).replace('%2F', '/')
sorted_params = sorted(list(http_params.items()), key=lambda http_params: http_params[0])
params = []
for (key, value) in sorted_params:
if value is None or len(value) == 0:
continue
params.append(urllib.parse.quote(key) + '=' + urllib.parse.quote(value))
return canonicalized + '?' + '&'.join(params)
def generateDate(self, format="%Y-%m-%dT%H:%M:%SZ", timestamp=None):
if timestamp is None:
return time.strftime(format, time.gmtime())
else:
return time.strftime(format, timestamp)
def generateNonce(self):
return str(int(time.time() * 100)) + str(random.randint(1000, 9999))
def __canonicalizedHeaders(self, request_header):
header = {}
for key, value in request_header.items():
if key is None or value is None:
continue
k = key.strip(' \t')
v = value.strip(' \t')
if k.startswith('X-Opensearch-') and len(v) > 0:
header[k] = v
if len(header) == 0:
return ''
sorted_header = sorted(list(header.items()), key=lambda header: header[0])
canonicalized = ''
for (key, value) in sorted_header:
canonicalized += (key.lower() + ':' + value + '\n')
return canonicalized
# 构建Request Header
def buildRequestHeader(self, uri, access_key, secret, http_params, http_header):
request_header = copy.deepcopy(http_header)
if 'Content-MD5' not in request_header:
request_header['Content-MD5'] = ''
if 'Content-Type' not in request_header:
request_header['Content-Type'] = 'application/json'
if 'Date' not in request_header:
request_header['Date'] = self.generateDate()
if 'X-Opensearch-Nonce' not in request_header:
request_header['X-Opensearch-Nonce'] = self.generateNonce()
if 'Authorization' not in request_header:
request_header['Authorization'] = self.buildAuthorization(uri,
access_key,
secret,
http_params,
request_header)
key_del = []
for key, value in request_header.items():
if value is None:
key_del.append(key)
for key in key_del:
del request_header[key]
return request_header
api = V3Api(address=internet_host, port='80')
def search(params, appname, fetch_fields):
'''
开放搜索查询
:param params: 查询条件
:param appname: app名称
:param fetch_fields: 返回字段
:return:
'''
query_params = {'query': '&&'.join(params.values()), 'fetch_fields': fetch_fields}
results = api.runQuery(app_name=appname,
access_key=accesskey_id,
secret=accesskey_secret,
http_params=query_params,
http_header={})
if results[0] == 200 and results[2]['status'] != 'FAIL':
return results[2]['result']
elif results[0] == 200:
logger.error(results[2]['errors'])
logger.error(query_params)
return '查询失败'
def land_search_of_area(areas, coordinates, limit=1):
'''
查询指定区域内多边形内的土地
:param coordinates: 类似'121.415652\,31.299175\,121.44771\,31.307169\,121.451723\,31.297287\,121.449727\,31.289164\,121.442088\,31.28513\,121.434364\,31.287165'
:return:
'''
query = ' OR '.join('area:"{}"'.format(area) for area in areas.strip(' ,').split(','))
fetch_fields = 'landid;area;plate;landname;electronicmap;location'
limit_str = 'start:0,hit:{},'.format(limit)
params = {
'query': 'query={}'.format(query),
'config': 'config={}format:json'.format(limit_str),
'filter': 'filter=in_query_polygon("polygons",location)>0',
'kvpairs': 'kvpairs=polygons:{}'.format(coordinates),
}
app_name = land_name
return search(params, app_name, fetch_fields)
def land_search(coordinates, limit=1):
'''
查询多边形内的土地
:param coordinates: 类似'121.415652\,31.299175\,121.44771\,31.307169\,121.451723\,31.297287\,121.449727\,31.289164\,121.442088\,31.28513\,121.434364\,31.287165'
:return:
'''
fetch_fields = 'landid;color;landname;electronicmap;location'
limit_str = 'start:0,hit:{},'.format(limit)
params = {
'query': 'query=area:"嘉定" OR area:"奉贤" OR area:"宝山" OR area:"崇明" OR area:"徐汇" OR area:"普陀" OR area:"杨浦" OR area:"松江" OR area:"浦东" OR area:"虹口" OR area:"金山" OR area:"长宁" OR area:"闵行" OR area:"青浦" OR area:"静安" OR area:"黄浦"',
'config': 'config={}format:json'.format(limit_str),
'filter': 'filter=in_query_polygon("polygons",location)>0',
'kvpairs': 'kvpairs=polygons:{}'.format(coordinates),
}
app_name = land_name
return search(params, app_name, fetch_fields)
def build_search(coordinates, limit=1):
'''
查询多边形内的幢号
:param coordinates: 类似'121.415652\,31.299175\,121.44771\,31.307169\,121.451723\,31.297287\,121.449727\,31.289164\,121.442088\,31.28513\,121.434364\,31.287165'
:return:
'''
fetch_fields = 'id;floorno;buildingsid_c;coordinate'
limit_str = 'start:0,hit:{},'.format(limit)
params = {
'query': 'query=area:"嘉定" OR area:"奉贤" OR area:"宝山" OR area:"崇明" OR area:"徐汇" OR area:"普陀" OR area:"杨浦" OR area:"松江" OR area:"浦东" OR area:"虹口" OR area:"金山" OR area:"长宁" OR area:"闵行" OR area:"青浦" OR area:"静安" OR area:"黄浦"',
'config': 'config={}format:json'.format(limit_str),
'filter': 'filter=in_query_polygon("polygons",location)>0',
'kvpairs': 'kvpairs=polygons:{}'.format(coordinates),
}
app_name = buildings_name
return search(params, app_name, fetch_fields)
if __name__ == '__main__':
# land_res = land_search(
# '121.415652\,31.299175\,121.44771\,31.307169\,121.451723\,31.297287\,121.449727\,31.289164\,121.442088\,31.28513\,121.434364\,31.287165')
land_res = build_search(
'121.415652\,31.299175\,121.44771\,31.307169\,121.451723\,31.297287\,121.449727\,31.289164\,121.442088\,31.28513\,121.434364\,31.287165')
# land_res = land_search_of_area("静安,闵行",
# '121.415652\,31.299175\,121.44771\,31.307169\,121.451723\,31.297287\,121.449727\,31.289164\,121.442088\,31.28513\,121.434364\,31.287165')
print(land_res)