0. 准备工作
在使用以下Python程序爬取高德地图地铁站点数据前,需要先在“高德开放平台”(网站:高德开放平台 | 高德地图API)申请一个API Key。具体操作为:注册一个“高德开放平台”账号,找到右上角的控制台,如下图所示。
然后按照下图所示序号,按照顺序依次操作。
最终你将获得一个 Key,如下图所示,将此 Key复制到下面的程序【2. 获取 API Key】中的your_default_key_here的位置,替换掉your_default_key_here。
注意:使用Key爬取数据时会有爬取次数的限制,如果超过爬取次数仍然运行程序强制爬取数据,会被封号。
详细的爬取程序详解如下:
1. 导入所需的模块
import os
import requests
import json
import pandas as pd
import time
- os: 用于与操作系统交互,在这里用于获取环境变量中的 API Key。
- requests: 用于发送 HTTP 请求,获取高德地图的地铁站数据。
- json: 用于处理 JSON 格式的数据。
- pandas: 用于处理数据并将其保存为 CSV 格式。
- time: 用于在 API 请求之间添加延迟,避免请求过于频繁。
2. 获取 API Key
API_KEY = os.getenv('GAODE_API_KEY', 'your_default_key_here')
- 这里我们使用
os.getenv
函数从环境变量中获取 API Key。如果没有找到对应的环境变量,则使用默认的 Key'your_default_key_here'
。
3. 初始化数据列表
col = ['metro_line', 'district', 'station_name', 'longitude', 'latitude']
all_stations = []
- col: 定义 CSV 文件的列名。
- all_stations: 用于保存所有地铁站的数据,稍后会将这些数据写入到一个 Pandas DataFrame 中。
4. 循环获取每一页的数据
for page_number in range(100):
url_parameters = {
'key': API_KEY,
'types': '150500',
'city': '昆明',
'extensions': 'base',
'citylimit': 'true',
'offset': '20',
'page': str(page_number)
}
url = 'https://restapi.amap.com/v3/place/text?'
page_json = requests.get(url=url, params=url_parameters).json()
if not page_json['pois']:
print(f'爬取结束,共{page_number}页数据。')
break
for dic in page_json['pois']:
data_dic = {
'metro_line': dic['address'],
'district': dic['adname'],
'station_name': dic['name'],
'longitude': dic['location'].split(',')[0],
'latitude': dic['location'].split(',')[1]
}
all_stations.append(data_dic)
time.sleep(1)
- url_parameters: 定义 API 请求的参数,包括 API Key、类型(地铁站)、城市(昆明)、分页信息等。
- page_json: 获取当前页面的数据并将其解析为 JSON 格式。
- if not page_json['pois']: 检查当前页面是否有数据,如果没有数据,则跳出循环,结束爬取。
- data_dic: 从 JSON 数据中提取我们感兴趣的信息(地址、区县、站点名、经纬度),并将其存储在字典中。
- all_stations.append(data_dic): 将每个地铁站的数据添加到
all_stations
列表中。 - time.sleep(1): 添加1秒的延迟,以避免发送请求过于频繁,防止被API服务封禁。
5. 保存所有数据到 CSV 文件
data_columns = pd.DataFrame(all_stations, columns=col)
data_columns.to_csv('C:\\Users\\Administrator\\Desktop\\tram_station.csv', sep=',', index=False, encoding='utf-8', header=True)
- pd.DataFrame(all_stations, columns=col): 将收集到的所有地铁站数据转换为 Pandas DataFrame。
- to_csv: 将 DataFrame 保存为 CSV 文件,路径指定为
C:\\Users\\Administrator\\Desktop\\tram_station.csv
,使用 UTF-8 编码,不保存索引。
6. 详细解释
- 模块导入: 我们导入了一些必要的库,用于请求数据、处理数据并保存结果。
- API Key 获取: 通过从环境变量中获取 API Key,我们提高了安全性,并使得程序更加灵活,可以适应不同的开发环境。
- 数据收集: 通过循环,我们逐页请求数据,直到没有更多数据为止。每次请求都会将新的地铁站信息添加到
all_stations
列表中。 - 延迟: 在每次请求之间添加延迟是为了避免短时间内发送过多请求,这样可以防止 IP 被 API 服务暂时封禁。
- 数据保存: 收集到所有数据后,我们将其转换为 DataFrame,并一次性保存为 CSV 文件。这比每次迭代时保存数据更加高效。
7. 完整程序
# 1. 导入所需的模块
import os
import requests
import json
import pandas as pd
import time
# 2. 获取 API Key
API_KEY = os.getenv('GAODE_API_KEY', 'your_default_key_here')
# 3. 初始化数据列表
col = ['metro_line', 'district', 'station_name', 'longitude', 'latitude']
all_stations = []
# 4. 循环获取每一页的数据
for page_number in range(100):
url_parameters = {
'key': API_KEY,
'types': '150500',
'city': '昆明',
'extensions': 'base',
'citylimit': 'true',
'offset': '20',
'page': str(page_number)
}
url = 'https://restapi.amap.com/v3/place/text?'
page_json = requests.get(url=url, params=url_parameters).json()
if not page_json['pois']:
print(f'爬取结束,共{page_number}页数据。')
break
for dic in page_json['pois']:
data_dic = {
'metro_line': dic['address'],
'district': dic['adname'],
'station_name': dic['name'],
'longitude': dic['location'].split(',')[0],
'latitude': dic['location'].split(',')[1]
}
all_stations.append(data_dic)
time.sleep(1)
# 5. 保存所有数据到 CSV 文件
data_columns = pd.DataFrame(all_stations, columns=col)
data_columns.to_csv('C:\\Users\\Administrator\\Desktop\\tram_station.csv', sep=',', index=False, encoding='utf-8', header=True)