GIS小白如何快速搭建在线地图平台?Streamlit菜鸟教程,附WebGIS开发实战案例!

编程与开发
Dr.GIS
wowwwai GIS研习社 · 工具流程与项目排障

GIS小白如何快速搭建在线地图平台?Streamlit菜鸟教程,附WebGIS开发实战案例!这篇文章面向刚入门的 GIS 学生、数据分析人员和初级 WebGIS 开发者,目标很明确:不用先搭复杂前端框架,也不用从零写一套地图系统,而是用 Python、Streamlit 和常见 GIS 库,快速做出一个能展示点线面数据、支持图层切换和基础查询的在线地图平台原型。

引言:为什么 GIS 小白可以先用 Streamlit 搭在线地图平台

很多 GIS 初学者一听到在线地图平台,就会想到前端框架、地图服务、瓦片切片、数据库、服务器部署,学习路径一下子变得很长。实际上,如果你的目标是做课程作业、项目演示、数据成果汇报或内部原型验证,Streamlit 是一个很适合入门的选择。

Streamlit 是一个 Python Web 应用框架,特点是用少量 Python 代码就能生成可交互网页。对于 GIS 场景,它可以结合 GeoPandas、Folium、PyDeck、Leafmap、PostGIS 等工具,把矢量数据、栅格结果、统计图表和空间查询界面放到同一个页面中。

这篇教程不会把 Streamlit 说成万能的 WebGIS 平台。它更适合快速验证和轻量发布。如果你需要百万级并发、复杂编辑、权限系统或企业级地图服务,还需要结合专业 WebGIS 架构。但作为 GIS 小白入门在线地图平台,Streamlit 的门槛确实低很多。

GIS小白快速搭建在线地图平台 Streamlit菜鸟教程流程图
使用 Streamlit 搭建在线地图平台的基本流程:数据准备、Python 处理、地图渲染和网页发布。

背景:在线地图平台最小可用版本需要哪些功能

在正式写代码前,先不要急着追求“大而全”。对于 GIS 小白来说,一个在线地图平台的最小可用版本可以只包含以下功能:

  • 加载一份空间数据,例如 GeoJSON、Shapefile 或带经纬度的 CSV。
  • 在网页中显示交互式地图,支持缩放、平移和底图浏览。
  • 按属性字段进行筛选,例如按类型、行政区、等级筛选要素。
  • 点击地图要素后查看属性信息。
  • 展示一个简单统计结果,例如数量统计、面积汇总或分类图表。
  • 可以在本机运行,也可以部署到 Streamlit Community Cloud、服务器或内网环境。

这类平台不一定要一开始就接入地图服务。对于小规模数据,直接读取 GeoJSON 或 CSV 并在浏览器端展示,已经可以完成很多教学和演示任务。等数据量变大,再逐步引入 PostGIS、GeoServer、矢量瓦片或缓存服务。

原理:Streamlit 做 WebGIS 的核心思路

Streamlit 做 WebGIS 的核心思路可以概括为三层:数据层、处理层和展示层。

1. 数据层:准备 GIS 数据

数据层负责存放空间数据。入门阶段建议优先使用以下格式:

  • GeoJSON:适合 WebGIS 展示,浏览器和 Python 都支持较好。
  • CSV:适合点位数据,至少需要经度字段和纬度字段。
  • Shapefile:传统 GIS 常用格式,但在 Web 项目中通常需要转换或打包处理。
  • GeoPackage:比 Shapefile 更现代,适合保存多个图层和较完整字段信息。

如果你是初学者,建议先把数据统一整理成 GeoJSON 或 CSV。这样代码更短,排错也更容易。

2. 处理层:用 Python 清洗和筛选数据

处理层通常由 GeoPandas、Pandas 或数据库查询完成。常见任务包括:

  • 读取矢量文件。
  • 检查坐标系是否为 WGS84,经纬度坐标通常使用 EPSG:4326。
  • 删除空几何和错误几何。
  • 按字段筛选要素。
  • 计算数量、面积、长度或分类统计。

很多在线地图显示异常,本质不是 Streamlit 的问题,而是数据坐标系、字段编码、几何有效性或文件路径出了问题。

3. 展示层:把地图嵌入 Streamlit 页面

展示层可以使用不同地图组件。入门阶段最常用的是 Folium 和 PyDeck:

  • Folium:基于 Leaflet,适合点线面展示、弹窗、图层控制和常规交互地图。
  • PyDeck:基于 deck.gl,适合较炫的可视化效果,例如热力、柱状、轨迹和大规模点数据。
  • Leafmap:封装了多种 GIS 与遥感数据展示能力,适合更偏 GIS 分析的场景。

本文用 Streamlit 加 Folium 来做一个菜鸟级 WebGIS 开发实战案例,因为它的学习曲线最平缓。

步骤:Streamlit 菜鸟教程,从零搭建在线地图平台

步骤 1:准备 Python 环境

建议使用 Python 3.10 或以上版本,并创建一个独立虚拟环境。这样可以避免 GIS 库版本冲突。

python -m venv venv

# Windows
venvScriptsactivate

# macOS / Linux
source venv/bin/activate

安装本文需要的库:

pip install streamlit pandas geopandas folium streamlit-folium

如果 GeoPandas 安装失败,通常是 GDAL、Fiona、pyproj 等依赖导致的。Windows 用户可以优先考虑使用 Conda 环境:

conda create -n streamlit_gis python=3.10
conda activate streamlit_gis
conda install -c conda-forge geopandas folium streamlit streamlit-folium

步骤 2:准备项目目录

建立一个简单项目目录:

streamlit-gis-demo/
  app.py
  data/
    sample_points.csv
    study_area.geojson

如果你暂时没有数据,可以先准备一份点位 CSV,字段示例如下:

name,type,lon,lat,value
监测点A,水质,116.391,39.907,85
监测点B,空气,116.410,39.915,72
监测点C,噪声,116.370,39.895,63

注意,经度字段是 lon,纬度字段是 lat。不要把经纬度顺序写反,这是 GIS 小白最常见的错误之一。

步骤 3:编写第一个 Streamlit 页面

在 app.py 中写入以下代码:

import streamlit as st
import pandas as pd
import folium
from streamlit_folium import st_folium

st.set_page_config(page_title="GIS 在线地图平台 Demo", layout="wide")

st.title("GIS 在线地图平台 Demo")
st.write("这是一个使用 Streamlit 和 Folium 搭建的 WebGIS 入门案例。")

df = pd.read_csv("data/sample_points.csv")

st.sidebar.header("图层筛选")
type_list = sorted(df["type"].unique())
selected_types = st.sidebar.multiselect(
    "选择监测类型",
    type_list,
    default=type_list
)

filtered = df[df["type"].isin(selected_types)]

center_lat = filtered["lat"].mean() if not filtered.empty else df["lat"].mean()
center_lon = filtered["lon"].mean() if not filtered.empty else df["lon"].mean()

m = folium.Map(
    location=[center_lat, center_lon],
    zoom_start=12,
    tiles="OpenStreetMap"
)

for _, row in filtered.iterrows():
    popup_text = f"""
    名称:{row['name']}<br>
    类型:{row['type']}<br>
    数值:{row['value']}
    """
    folium.Marker(
        location=[row["lat"], row["lon"]],
        popup=popup_text,
        tooltip=row["name"]
    ).add_to(m)

st.subheader("在线地图")
st_folium(m, width=1000, height=600)

st.subheader("属性表")
st.dataframe(filtered)

st.subheader("分类统计")
count_df = filtered.groupby("type").size().reset_index(name="数量")
st.bar_chart(count_df.set_index("type"))

运行应用:

streamlit run app.py

浏览器会自动打开本地地址,通常是 http://localhost:8501。到这里,一个最简单的 Streamlit 在线地图平台已经能运行了。

步骤 4:加载 GeoJSON 面数据

如果你需要展示行政区、研究区或地块边界,可以加载 GeoJSON 面数据。示例代码如下:

import geopandas as gpd

gdf = gpd.read_file("data/study_area.geojson")

if gdf.crs is not None and gdf.crs.to_epsg() != 4326:
    gdf = gdf.to_crs(epsg=4326)

folium.GeoJson(
    gdf,
    name="研究区边界",
    tooltip=folium.GeoJsonTooltip(fields=[col for col in gdf.columns if col != "geometry"][:3])
).add_to(m)

folium.LayerControl().add_to(m)

这里的关键点是坐标系。Web 地图通常以经纬度作为输入,如果你的数据是投影坐标,例如 CGCS2000 高斯投影、UTM 或地方坐标,直接加载后可能出现地图偏移、要素不显示或飞到海外的问题。

步骤 5:把筛选条件做成侧边栏

在线地图平台不能只看图,还要能按属性查询。Streamlit 的侧边栏很适合做筛选面板。常见控件包括:

  • multiselect:多选分类字段。
  • selectbox:单选行政区、年份或图层。
  • slider:筛选数值范围,例如人口、面积、监测值。
  • text_input:输入名称关键字查询。

例如增加一个数值范围筛选:

min_value = int(df["value"].min())
max_value = int(df["value"].max())

value_range = st.sidebar.slider(
    "选择数值范围",
    min_value=min_value,
    max_value=max_value,
    value=(min_value, max_value)
)

filtered = df[
    (df["type"].isin(selected_types)) &
    (df["value"] >= value_range[0]) &
    (df["value"] <= value_range[1])
]

这样,地图、属性表和统计图就会随着筛选条件同步变化。这正是 Streamlit 搭建在线地图平台最适合初学者的地方:交互逻辑主要用 Python 完成,不需要先写大量 JavaScript。

步骤 6:增加文件上传功能

如果想让用户上传自己的 CSV 点位数据,可以使用 file_uploader:

uploaded_file = st.sidebar.file_uploader("上传 CSV 点位数据", type=["csv"])

if uploaded_file is not None:
    df = pd.read_csv(uploaded_file)
else:
    df = pd.read_csv("data/sample_points.csv")

建议对上传数据做字段检查,避免用户上传错误文件后程序直接报错:

required_cols = {"name", "type", "lon", "lat"}

if not required_cols.issubset(set(df.columns)):
    st.error("CSV 必须包含 name、type、lon、lat 字段。")
    st.stop()

这一步非常重要。很多 WebGIS 原型失败,不是地图组件有问题,而是输入数据没有做校验。

步骤 7:部署到线上

完成本地测试后,可以选择以下部署方式:

  • 使用 Streamlit Community Cloud,适合公开演示和教学项目。
  • 部署到云服务器,适合内部项目或需要更高控制权限的场景。
  • 部署到单位内网服务器,适合不宜公开的数据。
  • 使用 Docker 封装环境,适合团队协作和长期维护。

最简单的方式是把项目上传到 GitHub,并在 Streamlit Community Cloud 中选择 app.py 作为入口文件。需要注意,项目根目录通常要包含 requirements.txt:

streamlit
pandas
geopandas
folium
streamlit-folium

如果项目包含敏感空间数据,不要上传到公开仓库。可以改用私有仓库、内网部署或数据库连接方式。

常见坑:Streamlit 做 WebGIS 最容易出错的地方

1. 地图空白或要素不显示

优先检查以下问题:

  • 经纬度字段是否写反。
  • 坐标是否在合理范围内,经度应大致在 -180 到 180,纬度应在 -90 到 90。
  • GeoDataFrame 是否已经转换到 EPSG:4326。
  • 数据是否为空,筛选条件是否把所有要素都过滤掉了。
  • 浏览器是否能访问所选底图服务。

2. 中文字段或中文路径报错

Shapefile 的中文编码问题比较常见。建议尽量使用 GeoPackage 或 GeoJSON。如果必须读取 Shapefile,可以检查 .cpg 文件,或在数据转换阶段统一编码。

3. 数据量稍大就变卡

如果直接把几万、几十万个要素塞进浏览器,Streamlit 和 Folium 都可能变慢。解决思路包括:

  • 先按行政区、类别或时间筛选,再加载地图。
  • 对线面数据做简化,减少节点数量。
  • 点数据可以改用聚合、热力图或 PyDeck。
  • 大数据量场景应考虑 PostGIS、矢量瓦片或后端分页查询。

4. 面积和距离计算不准

很多初学者直接在 EPSG:4326 经纬度坐标下计算面积和距离,这会导致结果不准确。正确做法是先投影到适合研究区的投影坐标系,再计算面积或长度。

gdf_projected = gdf.to_crs(epsg=3857)
gdf_projected["area_m2"] = gdf_projected.area

EPSG:3857 可用于一般展示和粗略计算,但如果是正式面积统计,最好选择符合研究区的等面积投影或当地标准投影。

5. 线上部署后本地路径失效

本地可以运行,不代表线上一定能运行。部署时要检查:

  • 数据文件是否已经提交到项目目录。
  • 路径是否使用相对路径,而不是本机绝对路径。
  • requirements.txt 是否包含全部依赖。
  • 线上环境是否支持 GeoPandas 所需的底层库。

方法比较:Streamlit、传统 WebGIS 和 GIS 桌面软件怎么选

方案 适合场景 优点 限制
Streamlit + Folium 教学演示、数据看板、轻量在线地图平台原型 Python 上手快,开发效率高,适合 GIS 小白 复杂前端交互和大规模并发能力有限
QGIS / ArcGIS Pro 专业数据处理、制图、空间分析 工具成熟,分析能力强,适合桌面 GIS 工作流 不适合直接发布成在线交互平台
Leaflet / OpenLayers 正式 WebGIS 前端开发 前端控制能力强,生态成熟 需要掌握 JavaScript、地图服务和前端工程
PostGIS + GeoServer + 前端框架 企业级 WebGIS、多人访问、空间数据库管理 可扩展性强,适合长期系统建设 架构复杂,部署和维护成本更高
PyDeck / deck.gl 大规模点数据、三维效果、动态可视化 可视化效果强,适合数据展示 传统 GIS 编辑和属性查询需要额外开发

如果你是 GIS 小白,建议路线是:先用 Streamlit 做出可用原型,再根据项目规模决定是否升级到 Leaflet、OpenLayers、PostGIS 或 GeoServer 架构。不要一开始就把系统做得过重。

检查清单:上线前逐项确认

  • 数据坐标系是否统一为 Web 地图可显示的经纬度坐标。
  • 经度、纬度字段是否没有写反。
  • 是否处理了空值、重复值和无效几何。
  • 筛选条件为空时是否有提示,而不是直接报错。
  • 地图、属性表和统计图是否使用同一份筛选后的数据。
  • 是否准备了 requirements.txt。
  • 是否避免上传敏感 GIS 数据到公开仓库。
  • 线上部署环境是否能正常安装 GeoPandas 等依赖。
  • 大数据量图层是否做了简化、筛选或聚合。
  • 弹窗字段是否经过筛选,避免一次展示过多无关属性。

经验建议:先做一个只支持一种数据、一张地图、一个筛选条件的版本。确认流程跑通后,再逐步增加图层、图表、上传、查询和部署功能。

FAQ:Streamlit 在线地图平台常见问题

Q1:Streamlit 能不能替代专业 WebGIS 开发?

不能完全替代。Streamlit 适合快速搭建在线地图平台原型、数据看板和教学案例。如果要做复杂权限、多人编辑、地图服务管理、空间数据库和高并发访问,仍然建议使用 PostGIS、GeoServer、Leaflet、OpenLayers 或 Cesium 等更完整的 WebGIS 技术栈。

Q2:GIS 小白学 Streamlit 之前需要会前端吗?

不需要先系统学习前端。Streamlit 的优势就是用 Python 生成网页界面。你只需要掌握基础 Python、Pandas 数据处理和一点 GIS 坐标系知识,就可以完成入门级在线地图平台。

Q3:Streamlit 加 Folium 可以加载 Shapefile 吗?

可以,但通常需要先用 GeoPandas 读取 Shapefile,再转换为 GeoJSON 形式传给 Folium。需要注意 Shapefile 的编码、多个配套文件是否完整,以及坐标系是否正确。

Q4:为什么我的点位显示到海上或国外?

最常见原因是经纬度顺序写反,或者数据坐标系不是 EPSG:4326。Folium 的点位顺序通常写成 location=[纬度, 经度],而很多表格字段习惯写成 lon、lat。这里一定要仔细检查。

Q5:Streamlit 在线地图平台适合展示遥感影像吗?

可以展示部分栅格结果,但不建议直接把很大的遥感影像文件塞进 Streamlit 页面。更合理的方式是先把影像发布为瓦片服务,或生成轻量化的 PNG、COG、XYZ 瓦片,再在地图组件中加载。

Q6:没有服务器能不能发布 Streamlit 应用?

可以。公开演示项目可以使用 Streamlit Community Cloud。只要项目代码放在 GitHub,并准备好 requirements.txt,就可以比较快地发布。但如果数据敏感,建议使用私有部署或内网服务器。

Q7:这个案例能不能连接 PostGIS?

可以。入门阶段建议先用 CSV 或 GeoJSON,等流程熟悉后再连接 PostGIS。连接 PostGIS 后,可以把属性筛选和空间查询放在数据库中完成,适合数据量更大、查询更复杂的在线地图平台。

结论:先用 Streamlit 跑通 WebGIS 原型,再逐步升级架构

对于 GIS 小白来说,快速搭建在线地图平台的关键不是一开始掌握所有 WebGIS 技术,而是先跑通一个完整闭环:准备数据、读取数据、显示地图、增加筛选、展示属性、完成部署。Streamlit 的价值就在这里,它让你可以用熟悉的 Python 快速完成 WebGIS 开发实战案例。

当你的项目只是课程展示、业务汇报、数据看板或原型验证时,Streamlit 加 Folium 已经足够实用。当数据量增加、访问人数变多、交互需求变复杂时,再逐步引入 PostGIS、GeoServer、Leaflet、OpenLayers 或 Cesium。这样学习路线更稳,也更符合真实 GIS 项目的成长过程。