高德爬虫2.0
- 写在最前面
- 结果展示
- getcity:获取与特定关键字相关的城市信息
- getpoi_page+hand:获取和处理高德地图API返回的POI数据
- getpois:根据城市名称和分类关键字获取POI数据
- 主函数:读取品牌名称,并根据品牌名称获取相关城市的POI数据并将其写入Excel文件
- 全部代码
写在最前面
修改前日期:2021-06-05 00:03:50
修改后:增加代码解析(因为质量分太低了。。。)
www一个月断断续续的更改,函数循环加主体循环把自己无限绕进去了,终于改完了
感谢@Fzy,@Tj,@Xk的指导
结果展示
读取品牌名称,并根据品牌名称获取相关城市的POI数据,并将其写入Excel文件
getcity:获取与特定关键字相关的城市信息
这个def没有循环来处理多页数据的情况,因此只能获取第一页的数据。如果需要获取更多页的数据,需要添加一个循环,并在每次循环迭代中增加 i
的值以获取下一页的数据。
- 定义函数
getcity(keywords)
:这个函数接受一个参数keywords
,用于指定关键字,即要搜索的城市名称或关键词。 - 定义变量
url1
:这个变量存储了一个URL字符串,指向高德地图的一个API端点。该API用于搜索与给定关键字相关的地点信息。 - 初始化变量
i
:这个变量表示当前爬取的页面信息。默认情况下,它被设置为0,意味着从第一页开始获取数据。可以通过增加i
的值来获取更多页面的数据。 - 构建请求URL
req_url1
:这个URL包括了一系列参数,包括 API 密钥(amap_web_key
)、扩展参数、关键字(通过quote(keywords)
进行URL编码)、偏移量(offset=25
表示每页返回25个结果)、页数(通过str(i)
来表示当前页数)和输出格式(JSON)。 - 发送HTTP请求:使用
urllib.request.urlopen
方法向req_url1
发送HTTP GET请求,从高德地图API获取数据。 - 处理响应数据:将响应数据解码为UTF-8编码,并使用
json.loads
方法将其解析为Python字典对象,存储在result1
中。 - 初始化城市列表
city_list
。 - 尝试提取城市信息:在
result1
中,尝试访问键为’suggestion’的字典,然后访问其中的’cities’键。如果这些键存在,将城市名称添加到city_list
中。如果键不存在或发生异常,代码会继续执行,不会引发错误。 - 最后,打印城市列表
city_list
并返回它。
代码中没有循环来处理多页数据的情况,因此只能获取第一页的数据。如果需要获取更多页的数据,需要添加一个循环,并在每次循环迭代中增加 i
的值以获取下一页的数据。
def getcity(keywords):
url1 = "https://restapi.amap.com/v3/place/text"
i = 0 # 爬取的页面信息,i=2时即爬取第2页的数据。当 result['count']=0 时即此页面已经无信息,爬取所有数据时可以用此终止循环
req_url1 = poi_search_url + "?key=" + amap_web_key + '&extensions=all&keywords=' + quote(
keywords) + '&offset=25' + '&page=' + str(i) + '&output=json'
data1 = {}
f = request.urlopen(req_url1)
data1 = f.read()
data1 = data1.decode('utf-8')
result1 = json.loads(data1)
city_list = []
try:
for i in result1['suggestion']['cities']:
# print(i['name'])
city_list.append(i['name'])
except:
pass
print(city_list)
return city_list
getpoi_page+hand:获取和处理高德地图API返回的POI数据
这段代码包含两个函数,用于获取和处理高德地图API返回的POI(兴趣点)数据。
getpoi_page(cityname, keywords, page)
函数:
- 该函数接受三个参数:
cityname
(城市名称)、keywords
(关键词)和page
(页数)。 - 它构建一个URL,向高德地图的POI搜索API发送HTTP GET请求,以获取与给定城市和关键词相关的POI数据。
- 请求URL包括API密钥(
amap_web_key
)、扩展参数、关键词、城市名称、城市限制(citylimit=true
表示仅在给定城市范围内搜索)、偏移量(offset=25
表示每页返回25个结果)、页数和输出格式(JSON)。 - 使用
urllib.request.urlopen
方法发送HTTP请求,然后读取响应数据并将其解码为UTF-8编码的字符串。 - 最后,返回获取到的数据。
hand(poilist, result)
函数:
- 该函数接受两个参数:
poilist
(POI数据列表)和result
(包含POI数据的字典)。 - 它从
result
字典中提取pois
键的值,该值是一个包含POI信息的列表。 - 使用
for
循环遍历pois
列表,并将每个POI信息添加到poilist
列表中。
在hand
函数中,有一行代码注释掉了 # result = json.loads(result)
,这意味着在函数内部并没有将返回的数据解析为JSON格式。如果需要将返回的数据解析为JSON对象,可以取消注释这行代码并将数据解析为JSON。
# 单页获取pois,返回data
def getpoi_page(cityname, keywords, page):
req_url = poi_search_url + "?key=" + amap_web_key + '&extensions=all&keywords=' + quote(
keywords) + '&city=' + quote(cityname) + '&citylimit=true' + '&offset=25' + '&page=' + str(
page) + '&output=json'
data = ''
with request.urlopen(req_url) as f1:
data = f1.read()
data = data.decode('utf-8')
return data
# 将返回的poi数据装入集合返回
def hand(poilist, result):
# result = json.loads(result) # 将字符串转换为json
pois = result['pois']
for i in range(len(pois)):
poilist.append(pois[i])
getpois:根据城市名称和分类关键字获取POI数据
这段代码定义了一个函数 getpois(cityname, keywords)
,用于根据城市名称和分类关键字获取POI数据。下面是对这个函数的分析:
- 函数接受两个参数:
cityname
(城市名称)和keywords
(关键字),用于指定要搜索的城市和关键字。 - 初始化变量
i
为 1,用于表示当前要获取的页数。 - 初始化空列表
poilist
,该列表将用于存储获取到的所有POI数据。 - 使用
while
循环不断分页获取数据,直到没有更多数据可获取为止。 - 在每次循环迭代中,调用
getpoi_page(cityname, keywords, i)
函数,以获取指定城市和关键字的POI数据,并将结果存储在变量result
中。 - 打印
result
,这将显示每个分页的POI数据。 - 使用
json.loads(result)
将获取到的字符串数据解析为JSON对象。 - 在接下来的代码中,尝试检查
result
中是否包含count
键,以确定是否还有更多数据可获取。如果count
的值为'0'
,或者count
不在result
的键中,则跳出循环,表示没有更多数据可获取。 - 如果
count
不满足跳出条件,将当前分页的POI数据添加到poilist
列表中,调用hand(poilist, result)
函数。 - 增加
i
的值,以准备获取下一页的数据。 - 打印
poilist
,显示已获取的所有POI数据。 - 循环回到第5步,继续获取下一页的数据,直到没有更多数据可获取。
- 最后,返回包含所有获取到的POI数据的
poilist
列表。
# 根据城市名称和分类关键字获取poi数据
def getpois(cityname, keywords):
i = 1
poilist = []
while True: # 使用while循环不断分页获取数据
result = getpoi_page(cityname, keywords, i)
print(result)
result = json.loads(result) # 将字符串转换为json
# errors修改:如果没有找到数据,则跳出
try:
if (result['count'] == '0') | ('count' not in result.keys()):
break
except:
pass
# 将结果装入集合返回
hand(poilist, result)
i = i + 1
# print("______________________________")
print(poilist)
return poilist
主函数:读取品牌名称,并根据品牌名称获取相关城市的POI数据并将其写入Excel文件
用于读取品牌名称,并根据品牌名称获取相关城市的POI数据并将其写入Excel文件。
- 通过
load_workbook
函数从指定的Excel文件中加载工作表,该Excel文件位于路径 “D:/Desktop/1.xlsx”。 - 初始化一个空列表
classes
用于存储品牌名称。 - 使用
for
循环遍历Excel文件中第一个工作表 (sheets[0]
) 的第一列数据(列’A’),并将品牌名称添加到classes
列表中。注意,代码排除了第一行的标题行 “品牌名称”。 - 创建一个新的Excel工作簿对象
book
,并创建一个新的工作表sheet
,将其插入到工作簿的第一个位置。 - 初始化计数器
count
,用于跟踪写入的数据行数。 - 使用一个外层的
for
循环,遍历品牌名称列表classes
中的每个品牌。 - 在每个循环迭代中,初始化一个空列表
classes_all_pois
用于存储与该品牌相关的所有POI数据。 - 调用
getcity(clas)
函数,获取与品牌相关的城市列表city
。 - 使用一个内层的
for
循环,遍历城市列表city
中的每个城市名称,并调用getpois(cityname, clas)
函数获取该城市中与品牌相关的POI数据,并将其添加到classes_all_pois
列表中。 - 输出当前城区、品牌名称以及获取到的POI数据的总数。
- 调用
write_to_excel(classes_all_pois, clas, count)
函数,将获取到的POI数据写入Excel文件中,该函数的定义在代码中没有提供,可能用于将数据写入Excel。 - 更新计数器
count
,以反映已写入的数据行数。 - 输出所有城区的数据汇总,以及品牌名称写入成功的消息。
这段代码依赖于其他函数 getcity
、getpois
和 write_to_excel
的实现,并且能够正确地处理城市和POI数据的获取以及写入Excel文件的操作。此外,需要确保提供的Excel文件位于指定的路径上,并包含要处理的品牌名称数据。
# 读取品牌名称
# TODO 需要修改成自己的【需要处理的品牌】的文件的路径
sheets = load_workbook("D:/Desktop/1.xlsx").worksheets
classes = []
for col in sheets[0]['A']:
classes.append(col.value)
classes.remove('品牌名称')
print(classes)
book = openpyxl.Workbook()
sheet = book.create_sheet(index=0)
# 直接获取整个城市的POI数据
count = 2
for clas in classes:
classes_all_pois = []
city = getcity(clas)
for cityname in city:
pois_area = getpois(cityname, clas)
classes_all_pois.extend(pois_area)
print('当前城区:' + str(cityname) + ', 分类:' + str(clas) + ", 总的有" + str(len(pois_area)) + "条数据")
write_to_excel(classes_all_pois, clas, count)
count = count + len(classes_all_pois)
print("所有城区的数据汇总,总数为:" + str(len(classes_all_pois)))
print('================分类:' + str(clas) + "写入成功")
全部代码
# -*- coding:utf-8 -*-
'''
gaode.py
Created on Fri June 4 2021
@author: Wyt
'''
from urllib.parse import quote
from urllib import request
import json
import xlwt
from openpyxl import load_workbook
from transCoordinateSystem import gcj02_to_wgs84
import openpyxl
def getcity(keywords):
url1 = "https://restapi.amap.com/v3/place/text"
i = 0 # 爬取的页面信息,i=2时即爬取第2页的数据。当 result['count']=0 时即此页面已经无信息,爬取所有数据时可以用此终止循环
req_url1 = poi_search_url + "?key=" + amap_web_key + '&extensions=all&keywords=' + quote(
keywords) + '&offset=25' + '&page=' + str(i) + '&output=json'
data1 = {}
f = request.urlopen(req_url1)
data1 = f.read()
data1 = data1.decode('utf-8')
result1 = json.loads(data1)
city_list = []
try:
for i in result1['suggestion']['cities']:
# print(i['name'])
city_list.append(i['name'])
except:
pass
print(city_list)
return city_list
# 单页获取pois,返回data
def getpoi_page(cityname, keywords, page):
req_url = poi_search_url + "?key=" + amap_web_key + '&extensions=all&keywords=' + quote(
keywords) + '&city=' + quote(cityname) + '&citylimit=true' + '&offset=25' + '&page=' + str(
page) + '&output=json'
data = ''
with request.urlopen(req_url) as f1:
data = f1.read()
data = data.decode('utf-8')
return data
# 将返回的poi数据装入集合返回
def hand(poilist, result):
# result = json.loads(result) # 将字符串转换为json
pois = result['pois']
for i in range(len(pois)):
poilist.append(pois[i])
# 根据城市名称和分类关键字获取poi数据
def getpois(cityname, keywords):
i = 1
poilist = []
while True: # 使用while循环不断分页获取数据
result = getpoi_page(cityname, keywords, i)
print(result)
result = json.loads(result) # 将字符串转换为json
# errors修改:如果没有找到数据,则跳出
try:
if (result['count'] == '0') | ('count' not in result.keys()):
break
except:
pass
# 将结果装入集合返回
hand(poilist, result)
i = i + 1
# print("______________________________")
print(poilist)
return poilist
# def write_to_excel(classfield,allcol):
# print(classfield)
# # 一个Workbook对象,这就相当于创建了一个Excel文件
# book = openpyxl.Workbook()
# sheet = book.create_sheet(index=0)
# # 第一行(列标题)
# sheet.cell(1, 1,'品牌名称')
# sheet.cell(1, 2, '门店名称')
# sheet.cell(1, 3, '分类')
# sheet.cell(1, 4, '省')
# sheet.cell(1, 5, '市')
# sheet.cell(1, 6, '区/县')
# sheet.cell(1, 7, '地址')
# sheet.cell(1, 8, '经度')
# sheet.cell(1, 9, '维度')
# count=0
# for i in allcol:
# brand = i
# poilist = getpois(cityname,brand)
# print(brand)
# for i in range(len(poilist)):
# location = poilist[i]['location'] # 经纬度
# name = poilist[i]['name'] # 店名
# type = poilist[i]['type'] # 分类
# pname = poilist[i]['pname'] # 省
# cityname = poilist[i]['cityname'] # 市
# adname = poilist[i]['adname'] # 区/县
# address = poilist[i].get('address') # 地址
# lng = str(location).split(",")[0] # 经度
# lat = str(location).split(",")[1] # 纬度
# '''
# result = gcj02_to_wgs84(float(lng), float(lat))
# lng = result[0]
# lat = result[1]
# '''
# # 每一行写入
# # print(count + i + 1)
# sheet.cell(count + i + 2, 1, brand)
# sheet.cell(count + i + 2, 2, name)
# sheet.cell(count + i + 2, 3, type)
# sheet.cell(count + i + 2, 4, pname)
# sheet.cell(count + i + 2, 5, cityname)
# sheet.cell(count + i + 2, 6, adname)
# sheet.cell(count + i + 2, 7, address)
# sheet.cell(count + i + 2, 8, lng)
# sheet.cell(count + i + 2, 9, lat)
# print(brand+"写入成功!")
# count=count+len(poilist)
# book.save(r'total_data_test5555.xlsx')
#
# book.close()
# 数据写入excel
def write_to_excel( poilist, classfield,count):
sheet.cell(1, 1,'品牌名称')
sheet.cell(1, 2, '门店名称')
sheet.cell(1, 3, '分类')
sheet.cell(1, 4, '省')
sheet.cell(1, 5, '市')
sheet.cell(1, 6, '区/县')
sheet.cell(1, 7, '地址')
sheet.cell(1, 8, '经度')
sheet.cell(1, 9, '维度')
# poilist 代表的是爬取的所有的内容
for i in range(len(poilist)):
name = (poilist[i]['name'])
type = poilist[i]['type']
pname = poilist[i]['pname'] #省名称
cityname = poilist[i]['cityname'] # 市名称
adname = poilist[i]['adname'] #区/县
# errors修改:KeyErrors
# 使用dict内置的get(key[,default])方法。如果key存在,则返回其value,否则返回default。
address = poilist[i].get('address',' ')
location = poilist[i]['location']
lng = str(location).split(",")[0]
lat = str(location).split(",")[1]
#坐标转换
result = gcj02_to_wgs84(float(lng), float(lat))
lng = result[0]
lat = result[1]
print(count + i)
sheet.cell(count + i, 1, str(classfield))
sheet.cell(count + i, 2, str(name))
sheet.cell(count + i, 3, str(type))
sheet.cell(count + i , 4, str(pname))
sheet.cell(count + i, 5, str(cityname))
sheet.cell(count + i, 6, str(adname))
sheet.cell(count + i, 7, str(address))
sheet.cell(count + i, 8, str(lng))
sheet.cell(count + i, 9, str(lat))
# 最后,将以上操作保存到指定的Excel文件中
# TODO 需要设置写入的excel路径
book.save(r'D:/Desktop/total_data.xlsx')
# book.save(r'D:/Desktop/' + cityname + "_" + classfield + '.xls')
book.close()
#按各行政区分别获取
'''
for clas in classes:
classes_all_pois = []
for area in nanning_areas:
pois_area = getpois(area, clas)
print('当前城区:' + str(area) + ', 分类:' + str(clas) + ", 总的有" + str(len(pois_area)) + "条数据")
classes_all_pois.extend(pois_area)
print("所有城区的数据汇总,总数为:" + str(len(classes_all_pois)))
write_to_excel(classes_all_pois, cityname, clas)
print('================分类:' + str(clas) + "写入成功")
'''
# book = openpyxl.Workbook()
# sheet = book.create_sheet(index=0)
if __name__ == '__main__':
# 申请的密钥
# TODO 需要修改成为自己的密钥
amap_web_key = '3aae9df0e318a90227a9a5f5bc81847e'
# 要爬取的API根
poi_search_url = "http://restapi.amap.com/v3/place/text"
poi_boundary_url = "https://ditu.amap.com/detail/get/detail"
# cityname为需要爬取的POI所属的城市名,city_areas为城市下面的行政区,classes为多个POI分类名的集合.
# (中文名或者代码都可以,代码详见高德地图的POI分类编码表)
# classes = [ '1點點', '24客便利店']
# 读取品牌名称
# TODO 需要修改成自己的【需要处理的品牌】的文件的路径
sheets = load_workbook("D:/Desktop/1.xlsx").worksheets
classes = []
for col in sheets[0]['A']:
classes.append(col.value)
classes.remove('品牌名称')
print(classes)
book = openpyxl.Workbook()
sheet = book.create_sheet(index=0)
# 直接获取整个城市的POI数据
count = 2
for clas in classes:
classes_all_pois = []
city = getcity(clas)
for cityname in city:
pois_area = getpois(cityname, clas)
classes_all_pois.extend(pois_area)
print('当前城区:' + str(cityname) + ', 分类:' + str(clas) + ", 总的有" + str(len(pois_area)) + "条数据")
write_to_excel(classes_all_pois, clas, count)
count = count + len(classes_all_pois)
print("所有城区的数据汇总,总数为:" + str(len(classes_all_pois)))
print('================分类:' + str(clas) + "写入成功")