import pandas as pdimport requestsimport timeimport mathimport geopandas as gpdfrom shapely.geometry import Pointdef gcj02_to_wgs84(lng, lat): if not (lng > 73.66 and lng < 135.05 and lat > 3.86 and lat < 53.55): return lng, lat a = 6378137.0 ee = 0.00669342162296594323 def transform_lat(x, y): ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * math.sqrt(abs(x)) ret += (20.0 * math.sin(6.0 * x * math.pi) + 20.0 * math.sin(2.0 * x * math.pi)) * 2.0 / 3.0 ret += (20.0 * math.sin(y * math.pi) + 40.0 * math.sin(y / 3.0 * math.pi)) * 2.0 / 3.0 ret += (160.0 * math.sin(y / 12.0 * math.pi) + 320 * math.sin(y * math.pi / 30.0)) * 2.0 / 3.0 return ret def transform_lng(x, y): ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * math.sqrt(abs(x)) ret += (20.0 * math.sin(6.0 * x * math.pi) + 20.0 * math.sin(2.0 * x * math.pi)) * 2.0 / 3.0 ret += (20.0 * math.sin(x * math.pi) + 40.0 * math.sin(x / 3.0 * math.pi)) * 2.0 / 3.0 ret += (150.0 * math.sin(x / 12.0 * math.pi) + 300.0 * math.sin(x / 30.0 * math.pi)) * 2.0 / 3.0 return ret dlat = transform_lat(lng - 105.0, lat - 35.0) dlng = transform_lng(lng - 105.0, lat - 35.0) radlat = lat / 180.0 * math.pi magic = math.sin(radlat) magic = 1 - ee * magic * magic sqrtmagic = math.sqrt(magic) dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * math.pi) dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * math.pi) mglat = lat + dlat mglng = lng + dlng return lng * 2 - mglng, lat * 2 - mglatdef get_amap_coordinates(address, key): url = "https://restapi.amap.com/v3/geocode/geo" params = {"address": address, "key": key, "output": "json"} try: r = requests.get(url, params=params, timeout=8) if r.status_code == 200: j = r.json() if j.get("status") == "1" and int(j.get("count")) > 0: location = j["geocodes"][0]["location"] lng_gcj, lat_gcj = map(float, location.split(',')) return gcj02_to_wgs84(lng_gcj, lat_gcj) except: pass return None, Nonedef process_excel_with_coordinates(input_file, output_file, shp_file, key): df = pd.read_excel(input_file) if "经度" not in df.columns: df["经度"] = None if "纬度" not in df.columns: df["纬度"] = None for i, row in df.iterrows(): addr = str(row.get("地址", "")).strip() if not addr or addr == 'nan': continue lng_wgs, lat_wgs = get_amap_coordinates(addr, key) if lng_wgs: df.at[i, "经度"], df.at[i, "纬度"] = lng_wgs, lat_wgs print(f"处理成功 [{i + 1}]: {addr} -> WGS84: {lng_wgs:.6f}, {lat_wgs:.6f}") else: print(f"处理失败 [{i + 1}]: {addr}") time.sleep(0.1) df.to_excel(output_file, index=False) valid = df.dropna(subset=["经度", "纬度"]).copy() if not valid.empty: valid["geometry"] = valid.apply(lambda x: Point(float(x["经度"]), float(x["纬度"])), axis=1) gdf = gpd.GeoDataFrame(valid, geometry="geometry", crs="EPSG:4326") for col in gdf.columns: if gdf[col].dtype == 'object' and col != 'geometry': gdf[col] = gdf[col].astype(str) gdf.to_file(shp_file, encoding="utf-8") print("\n所有操作已完成,Shapefile 已生成。")if __name__ == "__main__": MY_KEY = "d8668f5a89842f71835d2c6cf652bb7c" in_path = r"C:\Users\Ayu\Documents\工作簿1.xlsx" out_path = r"C:\Users\Ayu\Documents\工作簿11.xlsx" shp_path = r"C:\Users\Ayu\Documents\工作簿11.shp" process_excel_with_coordinates(in_path, out_path, shp_path, MY_KEY)