Files
sixGuoDjango/wechat_项目工具包/腾讯地图/腾讯地图工具.py
T

196 lines
7.6 KiB
Python
Raw Normal View History

2026-08-02 14:07:04 +08:00
"""功能模块"""
import math
from typing import TypedDict, Union
import jmespath
import pydash
import requests
# WechatMapClass.haversine(lat1=32.
# 474664, lon1=119.893471, lat2=32.
# 471578, lon2=119.917068)
# WechatMapClass.addressToCoordinat
# eConversion(address="江苏省泰州市海陵区济川东路与青年南路交叉口东220米泰州万达广场(2号入口)")
# WechatMapClass.coordinateToAddressConversion(location="32.474664,119.893471")
# WechatMapClass.coordinateToAddressConversion(location="32.471578,119.917068")
class OriginPointOptional(TypedDict):
经度: Union[float, str]
纬度: Union[float, str]
from pydantic import BaseModel
class AdInfo(BaseModel):
city: str
adcode: int
nation: str
district: str
province: str
nation_code: int
class Location(BaseModel):
lat: float
lng: float
class Result(BaseModel):
ip: str
ad_info: AdInfo
location: Location
class IP解析地址模型Response(BaseModel):
result: Result
status: int
message: str
class wei地图工具:
"""注释"""
key = "7SNBZ-FLN63-LRA3S-YJBAK-XSHQ3-TGF5E" # 腾讯地图的key
# key = "LREBZ-PH5R7-2NIXW-H7JDB-CVHTK-4YFUJ" # 莫大帅注册地地图的腾讯地图的key
@classmethod
def 公式计算二点之间的距离(cls, orgin原点: OriginPointOptional, user原点: OriginPointOptional) -> float:
""""""
# 地球半径,单位为公里
R = 6371.0
# orgin原点: OriginPointOptional = {"纬度": 30.80377, "经度": 104.151812}
# user原点: OriginPointOptional = {"纬度": 30.80377, "经度": 104.151812}
# 将角度转换为弧度
orgin纬度 = math.radians(orgin原点.get("纬度"))
orgin经度 = math.radians(orgin原点.get("经度"))
user纬度 = math.radians(user原点.get("纬度"))
user经度 = math.radians(user原点.get("纬度"))
# 经纬度差值
经度差 = user经度 - orgin经度
纬度差 = user纬度 - orgin纬度
print(经度差, 纬度差)
# Haversine公式
a = math.sin(纬度差 / 2) ** 2 + math.cos(orgin纬度) * math.cos(user纬度) * math.sin(经度差 / 2) ** 2
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
# 计算两点间的距离
distance = R * c
print(f"The distance between two points is {distance} km.")
return distance
@classmethod
def 腾讯地图计算二点之间的距离(cls, toData终点: OriginPointOptional, fromData起点: OriginPointOptional):
""""""
fromStrDat = dict(sorted(fromData起点.items(), reverse=False))
fromStr = ",".join(fromStrDat.values())
toStrDat = dict(sorted(toData终点.items(), reverse=False))
toStr = ",".join(toStrDat.values())
print("排序后的值为", fromStr, toStr)
data = {"key": cls.key, "from": fromStr, "to": toStr}
url = f"https://apis.map.qq.com/ws/distance/v1/matrix?mode=driving"
res_data = requests.post(url=url, data=data)
print(res_data.json())
res_json = res_data.json() # type: dict
d = {
2026-08-06 20:39:45 +08:00
"status": 0,
"message": "Success",
"request_id": "9435209f1ee84219ae7826e65f577331",
"result": {
"rows": [{
"elements": [{
"distance": 3550, # 起点到终点的距离,单位:米
"duration": 651, # 表示从起点到终点的结合路况的时间,秒为单位注:步行/骑行方式(不计算耗时)以及起终点附近没有道路造成无法计算时,不返回本此节点
2026-08-02 14:07:04 +08:00
}],
}],
},
}
distance = jmespath.search(data=res_data.json(), expression="result.rows[0].elements[0].distance")
return distance
@classmethod
def 地址转换为坐标(cls, address: str):
""""""
url = f"https://apis.map.qq.com/ws/geocoder/v1/?address={address}"
res = requests.get(url=url, params={"key": cls.key}, )
d = {
2026-08-06 20:39:45 +08:00
"status": 0,
"message": "Success",
"request_id": "9b049a3ff13c4ac3bda3bb5a9fe0c0a8",
"result": {
"title": "泰州海陵万达广场",
"location": { # 解析到的坐标(GCJ02坐标系)
"lng": 119.917068, # 经度
"lat": 32.471578, # 纬度
2026-08-02 14:07:04 +08:00
},
2026-08-06 20:39:45 +08:00
"ad_info": { # 行政区划信息 object 是
"adcode": "321202", # string 是 行政区划代码,规则详见:行政区划代码说明
2026-08-02 14:07:04 +08:00
},
2026-08-06 20:39:45 +08:00
"address_components": {
"province": "江苏省",
"city": "泰州市",
"district": "海陵区",
"street": "济川东路",
"street_number": "",
2026-08-02 14:07:04 +08:00
},
2026-08-06 20:39:45 +08:00
"similarity": 0.99,
"deviation": 1000,
"reliability": 7, # 可信度参考:值范围 1 <低可信> - 10 <高可信>
"level": 11, # 解析精度级别,分为11个级别,一般>=9即可采用(定位到点,精度较高) 也可根据实际业务需求自行调整,完整取值表见下文。
2026-08-02 14:07:04 +08:00
},
}
@classmethod
def 经纬度转换为地址(cls, location):
""""""
pass
2026-08-06 20:39:45 +08:00
url = f"https://apis.map.qq.com/ws/geocoder/v1/?location={location}"
2026-08-02 14:07:04 +08:00
res = requests.get(url=url, params={"key": cls.key}, )
return res.json()
@classmethod
def ip地址转为地址(cls, x_forwarded_for: str | bool, ):
""""""
url = "https://apis.map.qq.com/ws/location/v1/ip"
response_data = requests.get(url=url, params={"key": cls.key, "ip": x_forwarded_for}, )
data = response_data.json() # type: dict
print(data)
resData = pydash.omit(data, "request_id")
d = {
2026-08-06 20:39:45 +08:00
"status": 0,
"message": "Success",
"request_id": "8805bff3303f42dd8a1cbcca3701cf63",
"result": {
"ip": "240e:3a3:b201:3f10:185c:efdb:c5b0:b95c",
"location": {
"lat": 32.49098,
"lng": 119.91956,
2026-08-02 14:07:04 +08:00
},
2026-08-06 20:39:45 +08:00
"ad_info": {
"nation": "中国",
"province": "江苏省",
"city": "泰州市",
"district": "海陵区",
"adcode": 321202,
"nation_code": 156,
2026-08-02 14:07:04 +08:00
},
},
}
# nation = jmespath.search(data=data, expression="result.ad_info.nation", ) # 国家
# province = jmespath.search(data=data, expression="result.ad_info.province", ) # 省份
# city = jmespath.search(data=data, expression="result.ad_info.city", )
# district = jmespath.search(data=data, expression="result.ad_info.district", ) # 区
# adcode = jmespath.search(data=data, expression="result.ad_info.adcode", ) # 区号
# ip = jmespath.search(data=data, expression="result.ip", )
# lat = jmespath.search(data=data, expression="result.location.lat", )
# lng = jmespath.search(data=data, expression="result.location.lng", )
return resData
2026-08-06 20:39:45 +08:00
if __name__ == "__main__":
2026-08-02 14:07:04 +08:00
# wei地图工具.腾讯地图计算二点之间的距离(toData终点={"纬度": "30.80377", "经度": "104.151812"}, fromData起点={"纬度": "30.80377", "经度": "104.151812"})
print(wei地图工具.ip地址转为地址(x_forwarded_for="119.84.150.100", ))