1. 百度地图POI数据爬取入门指南第一次接触百度地图POI数据爬取时我也被各种专业术语搞得一头雾水。POIPoint of Interest其实就是我们常说的兴趣点比如餐馆、医院、商场这些地点信息。而百度地图开放平台提供的API接口让我们能够批量获取这些数据。这在实际项目中非常有用比如做商业分析时需要统计某个区域的餐饮店铺分布或者做城市规划时需要了解医疗资源覆盖情况。要完成整个爬取流程我们需要先申请一个AKAccess Key这是调用百度地图API的钥匙。整个过程可以分为四个关键步骤注册开发者账号、创建应用获取AK、构造请求URL、解析返回的JSON数据。听起来可能有点复杂但跟着我的步骤操作你会发现其实很简单。我刚开始做的时候也踩过不少坑比如AK类型选错、忘记设置IP白名单等等这些经验教训都会在后续内容中详细说明。2. 申请百度地图AK的完整流程2.1 注册开发者账号首先打开百度地图开放平台官网点击右上角的注册按钮。这里有个小技巧建议使用企业邮箱注册因为个人邮箱可能会遇到验证问题。注册时需要填写基本信息包括手机号验证整个过程大概需要5分钟。注册完成后别急着退出系统通常会发送一封激活邮件记得去邮箱点击确认链接。2.2 创建应用获取AK登录后进入控制台找到应用管理-我的应用-创建应用。这里有几个关键设置需要注意应用名称建议取个有意义的名称比如XX项目POI采集应用类型根据你的使用场景选择浏览器端或服务端IP白名单如果是固定服务器调用就设置具体IP本地测试可以填0.0.0.0不推荐长期使用创建成功后系统会生成一个AK字符串这个就是我们的通行证。建议把它保存在安全的地方同时做好备份。我曾经因为电脑重装系统丢失过AK导致项目中断了半天。2.3 AK使用限制说明免费版的AK有调用频率限制未认证用户每天10万次每分钟6000次认证用户每天30万次每分钟1万次对于POI搜索接口每次请求最多返回20条记录通过分页参数可以获取最多400条数据。如果目标区域的数据量超过400条就需要采用网格划分的方法这个我们会在第4章详细讲解。3. 构造POI请求URL详解3.1 基础URL参数解析百度地图POI搜索接口的基础URL格式如下http://api.map.baidu.com/place/v2/search关键参数说明query搜索关键词如医院、餐厅region搜索区域可以是城市或省份page_size每页返回数量最大20page_num页码从0开始output返回格式json/xmlak你的访问密钥3.2 实战URL示例假设我们要搜索北京市的咖啡厅AK是your_ak那么请求URL应该是base_url http://api.map.baidu.com/place/v2/search params { query: 咖啡厅, region: 北京, page_size: 20, page_num: 0, output: json, ak: your_ak }可以用Python的requests库发送这个请求import requests response requests.get(base_url, paramsparams) data response.json() print(data)3.3 分页获取全部数据由于每次最多只能获取20条数据我们需要循环获取所有页面的数据all_pois [] page_num 0 while True: params[page_num] page_num response requests.get(base_url, paramsparams) data response.json() if not data.get(results): break all_pois.extend(data[results]) page_num 1 # 避免触发频率限制 time.sleep(0.1)4. 处理大数据量的高级技巧4.1 区域网格划分方法当某个区域的POI数量超过400条时我们需要将该区域划分为多个小网格分别查询。具体步骤获取目标城市的经纬度范围将区域划分为若干个小矩形对每个小矩形区域发起POI查询这里提供一个简单的网格划分函数def create_grid(bounds, rows10, cols10): 将矩形区域划分为网格 bounds: (min_lng, min_lat, max_lng, max_lat) rows: 行数 cols: 列数 min_lng, min_lat, max_lng, max_lat bounds lng_step (max_lng - min_lng) / cols lat_step (max_lat - min_lat) / rows grids [] for i in range(rows): for j in range(cols): grid_min_lng min_lng j * lng_step grid_max_lng grid_min_lng lng_step grid_min_lat min_lat i * lat_step grid_max_lat grid_min_lat lat_step grids.append((grid_min_lng, grid_min_lat, grid_max_lng, grid_max_lat)) return grids4.2 多线程爬取优化为了提高爬取效率可以使用多线程技术from concurrent.futures import ThreadPoolExecutor def fetch_pois(grid): # 实现单个网格的POI获取 pass grids create_grid(bounds) with ThreadPoolExecutor(max_workers5) as executor: results list(executor.map(fetch_pois, grids))5. JSON数据解析与存储5.1 解析返回的JSON结构百度地图返回的POI数据包含丰富的信息主要字段包括namePOI名称location经纬度(lng,lat)address详细地址telephone联系电话uid唯一标识detail_info详细信息如营业时间、评分等解析示例for poi in data[results]: print(f名称: {poi[name]}) print(f地址: {poi[address]}) print(f经纬度: {poi[location][lng]}, {poi[location][lat]}) if telephone in poi: print(f电话: {poi[telephone]})5.2 数据存储方案常见的存储方式有三种CSV文件适合小规模数据import csv with open(pois.csv, w, newline, encodingutf-8) as f: writer csv.writer(f) writer.writerow([名称, 地址, 经度, 纬度, 电话]) for poi in all_pois: writer.writerow([ poi[name], poi[address], poi[location][lng], poi[location][lat], poi.get(telephone, ) ])MySQL数据库适合大规模数据import pymysql conn pymysql.connect(hostlocalhost, userroot, password123456, dbpoi_db) cursor conn.cursor() sql CREATE TABLE IF NOT EXISTS pois ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), address VARCHAR(255), lng FLOAT, lat FLOAT, telephone VARCHAR(50), uid VARCHAR(50) ) cursor.execute(sql) insert_sql INSERT INTO pois (name, address, lng, lat, telephone, uid) VALUES (%s, %s, %s, %s, %s, %s) for poi in all_pois: cursor.execute(insert_sql, ( poi[name], poi[address], poi[location][lng], poi[location][lat], poi.get(telephone, ), poi[uid] )) conn.commit() conn.close()MongoDB适合非结构化数据from pymongo import MongoClient client MongoClient(mongodb://localhost:27017/) db client[poi_db] collection db[pois] collection.insert_many(all_pois)6. 常见问题与解决方案在实际项目中我遇到过各种奇怪的问题。比如有一次AK突然失效排查后发现是因为IP地址变化导致的白名单限制。还有一次爬取速度太快触发了百度地图的反爬机制。这里分享几个典型问题的解决方法AK无效或没有权限检查AK是否正确复制确认应用类型浏览器端/服务端选择正确检查IP白名单设置返回数据为空确认查询关键词是否正确检查区域参数是否有效尝试扩大搜索范围请求频率过高添加适当的延时如time.sleep(0.1)使用多个AK轮询考虑申请付费套餐提升配额数据不完整检查是否处理了所有分页对于大数据量区域使用网格划分验证返回结果中的total字段对于商业项目建议考虑使用百度地图的商业API服务它提供更高的调用限额和更稳定的服务保障。免费版适合个人学习和小型项目但在数据量和稳定性上都有一定限制。
百度地图POI数据爬取实战:从AK申请到JSON解析
1. 百度地图POI数据爬取入门指南第一次接触百度地图POI数据爬取时我也被各种专业术语搞得一头雾水。POIPoint of Interest其实就是我们常说的兴趣点比如餐馆、医院、商场这些地点信息。而百度地图开放平台提供的API接口让我们能够批量获取这些数据。这在实际项目中非常有用比如做商业分析时需要统计某个区域的餐饮店铺分布或者做城市规划时需要了解医疗资源覆盖情况。要完成整个爬取流程我们需要先申请一个AKAccess Key这是调用百度地图API的钥匙。整个过程可以分为四个关键步骤注册开发者账号、创建应用获取AK、构造请求URL、解析返回的JSON数据。听起来可能有点复杂但跟着我的步骤操作你会发现其实很简单。我刚开始做的时候也踩过不少坑比如AK类型选错、忘记设置IP白名单等等这些经验教训都会在后续内容中详细说明。2. 申请百度地图AK的完整流程2.1 注册开发者账号首先打开百度地图开放平台官网点击右上角的注册按钮。这里有个小技巧建议使用企业邮箱注册因为个人邮箱可能会遇到验证问题。注册时需要填写基本信息包括手机号验证整个过程大概需要5分钟。注册完成后别急着退出系统通常会发送一封激活邮件记得去邮箱点击确认链接。2.2 创建应用获取AK登录后进入控制台找到应用管理-我的应用-创建应用。这里有几个关键设置需要注意应用名称建议取个有意义的名称比如XX项目POI采集应用类型根据你的使用场景选择浏览器端或服务端IP白名单如果是固定服务器调用就设置具体IP本地测试可以填0.0.0.0不推荐长期使用创建成功后系统会生成一个AK字符串这个就是我们的通行证。建议把它保存在安全的地方同时做好备份。我曾经因为电脑重装系统丢失过AK导致项目中断了半天。2.3 AK使用限制说明免费版的AK有调用频率限制未认证用户每天10万次每分钟6000次认证用户每天30万次每分钟1万次对于POI搜索接口每次请求最多返回20条记录通过分页参数可以获取最多400条数据。如果目标区域的数据量超过400条就需要采用网格划分的方法这个我们会在第4章详细讲解。3. 构造POI请求URL详解3.1 基础URL参数解析百度地图POI搜索接口的基础URL格式如下http://api.map.baidu.com/place/v2/search关键参数说明query搜索关键词如医院、餐厅region搜索区域可以是城市或省份page_size每页返回数量最大20page_num页码从0开始output返回格式json/xmlak你的访问密钥3.2 实战URL示例假设我们要搜索北京市的咖啡厅AK是your_ak那么请求URL应该是base_url http://api.map.baidu.com/place/v2/search params { query: 咖啡厅, region: 北京, page_size: 20, page_num: 0, output: json, ak: your_ak }可以用Python的requests库发送这个请求import requests response requests.get(base_url, paramsparams) data response.json() print(data)3.3 分页获取全部数据由于每次最多只能获取20条数据我们需要循环获取所有页面的数据all_pois [] page_num 0 while True: params[page_num] page_num response requests.get(base_url, paramsparams) data response.json() if not data.get(results): break all_pois.extend(data[results]) page_num 1 # 避免触发频率限制 time.sleep(0.1)4. 处理大数据量的高级技巧4.1 区域网格划分方法当某个区域的POI数量超过400条时我们需要将该区域划分为多个小网格分别查询。具体步骤获取目标城市的经纬度范围将区域划分为若干个小矩形对每个小矩形区域发起POI查询这里提供一个简单的网格划分函数def create_grid(bounds, rows10, cols10): 将矩形区域划分为网格 bounds: (min_lng, min_lat, max_lng, max_lat) rows: 行数 cols: 列数 min_lng, min_lat, max_lng, max_lat bounds lng_step (max_lng - min_lng) / cols lat_step (max_lat - min_lat) / rows grids [] for i in range(rows): for j in range(cols): grid_min_lng min_lng j * lng_step grid_max_lng grid_min_lng lng_step grid_min_lat min_lat i * lat_step grid_max_lat grid_min_lat lat_step grids.append((grid_min_lng, grid_min_lat, grid_max_lng, grid_max_lat)) return grids4.2 多线程爬取优化为了提高爬取效率可以使用多线程技术from concurrent.futures import ThreadPoolExecutor def fetch_pois(grid): # 实现单个网格的POI获取 pass grids create_grid(bounds) with ThreadPoolExecutor(max_workers5) as executor: results list(executor.map(fetch_pois, grids))5. JSON数据解析与存储5.1 解析返回的JSON结构百度地图返回的POI数据包含丰富的信息主要字段包括namePOI名称location经纬度(lng,lat)address详细地址telephone联系电话uid唯一标识detail_info详细信息如营业时间、评分等解析示例for poi in data[results]: print(f名称: {poi[name]}) print(f地址: {poi[address]}) print(f经纬度: {poi[location][lng]}, {poi[location][lat]}) if telephone in poi: print(f电话: {poi[telephone]})5.2 数据存储方案常见的存储方式有三种CSV文件适合小规模数据import csv with open(pois.csv, w, newline, encodingutf-8) as f: writer csv.writer(f) writer.writerow([名称, 地址, 经度, 纬度, 电话]) for poi in all_pois: writer.writerow([ poi[name], poi[address], poi[location][lng], poi[location][lat], poi.get(telephone, ) ])MySQL数据库适合大规模数据import pymysql conn pymysql.connect(hostlocalhost, userroot, password123456, dbpoi_db) cursor conn.cursor() sql CREATE TABLE IF NOT EXISTS pois ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), address VARCHAR(255), lng FLOAT, lat FLOAT, telephone VARCHAR(50), uid VARCHAR(50) ) cursor.execute(sql) insert_sql INSERT INTO pois (name, address, lng, lat, telephone, uid) VALUES (%s, %s, %s, %s, %s, %s) for poi in all_pois: cursor.execute(insert_sql, ( poi[name], poi[address], poi[location][lng], poi[location][lat], poi.get(telephone, ), poi[uid] )) conn.commit() conn.close()MongoDB适合非结构化数据from pymongo import MongoClient client MongoClient(mongodb://localhost:27017/) db client[poi_db] collection db[pois] collection.insert_many(all_pois)6. 常见问题与解决方案在实际项目中我遇到过各种奇怪的问题。比如有一次AK突然失效排查后发现是因为IP地址变化导致的白名单限制。还有一次爬取速度太快触发了百度地图的反爬机制。这里分享几个典型问题的解决方法AK无效或没有权限检查AK是否正确复制确认应用类型浏览器端/服务端选择正确检查IP白名单设置返回数据为空确认查询关键词是否正确检查区域参数是否有效尝试扩大搜索范围请求频率过高添加适当的延时如time.sleep(0.1)使用多个AK轮询考虑申请付费套餐提升配额数据不完整检查是否处理了所有分页对于大数据量区域使用网格划分验证返回结果中的total字段对于商业项目建议考虑使用百度地图的商业API服务它提供更高的调用限额和更稳定的服务保障。免费版适合个人学习和小型项目但在数据量和稳定性上都有一定限制。