高德爬虫2.0

  • 写在最前面
  • 结果展示
  • getcity:获取与特定关键字相关的城市信息
  • getpoi_page+hand:获取和处理高德地图API返回的POI数据
  • getpois:根据城市名称和分类关键字获取POI数据
  • 主函数:读取品牌名称,并根据品牌名称获取相关城市的POI数据并将其写入Excel文件
  • 全部代码


写在最前面

修改前日期:2021-06-05 00:03:50
修改后:增加代码解析(因为质量分太低了。。。)

www一个月断断续续的更改,函数循环加主体循环把自己无限绕进去了,终于改完了

感谢@Fzy,@Tj,@Xk的指导

结果展示

读取品牌名称,并根据品牌名称获取相关城市的POI数据,并将其写入Excel文件

python爬取高德地图POI点 爬取高德地图数据_python

getcity:获取与特定关键字相关的城市信息

这个def没有循环来处理多页数据的情况,因此只能获取第一页的数据。如果需要获取更多页的数据,需要添加一个循环,并在每次循环迭代中增加 i 的值以获取下一页的数据。

  1. 定义函数 getcity(keywords):这个函数接受一个参数 keywords,用于指定关键字,即要搜索的城市名称或关键词。
  2. 定义变量 url1:这个变量存储了一个URL字符串,指向高德地图的一个API端点。该API用于搜索与给定关键字相关的地点信息。
  3. 初始化变量 i:这个变量表示当前爬取的页面信息。默认情况下,它被设置为0,意味着从第一页开始获取数据。可以通过增加 i 的值来获取更多页面的数据。
  4. 构建请求URL req_url1:这个URL包括了一系列参数,包括 API 密钥(amap_web_key)、扩展参数、关键字(通过 quote(keywords) 进行URL编码)、偏移量(offset=25 表示每页返回25个结果)、页数(通过 str(i) 来表示当前页数)和输出格式(JSON)。
  5. 发送HTTP请求:使用 urllib.request.urlopen 方法向 req_url1 发送HTTP GET请求,从高德地图API获取数据。
  6. 处理响应数据:将响应数据解码为UTF-8编码,并使用 json.loads 方法将其解析为Python字典对象,存储在 result1 中。
  7. 初始化城市列表 city_list
  8. 尝试提取城市信息:在 result1 中,尝试访问键为’suggestion’的字典,然后访问其中的’cities’键。如果这些键存在,将城市名称添加到 city_list 中。如果键不存在或发生异常,代码会继续执行,不会引发错误。
  9. 最后,打印城市列表 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(兴趣点)数据。

  1. 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编码的字符串。
  • 最后,返回获取到的数据。
  1. 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数据。下面是对这个函数的分析:

  1. 函数接受两个参数:cityname(城市名称)和 keywords(关键字),用于指定要搜索的城市和关键字。
  2. 初始化变量 i 为 1,用于表示当前要获取的页数。
  3. 初始化空列表 poilist,该列表将用于存储获取到的所有POI数据。
  4. 使用 while 循环不断分页获取数据,直到没有更多数据可获取为止。
  5. 在每次循环迭代中,调用 getpoi_page(cityname, keywords, i) 函数,以获取指定城市和关键字的POI数据,并将结果存储在变量 result 中。
  6. 打印 result,这将显示每个分页的POI数据。
  7. 使用 json.loads(result) 将获取到的字符串数据解析为JSON对象。
  8. 在接下来的代码中,尝试检查 result 中是否包含 count 键,以确定是否还有更多数据可获取。如果 count 的值为 '0',或者 count 不在 result 的键中,则跳出循环,表示没有更多数据可获取。
  9. 如果 count 不满足跳出条件,将当前分页的POI数据添加到 poilist 列表中,调用 hand(poilist, result) 函数。
  10. 增加 i 的值,以准备获取下一页的数据。
  11. 打印 poilist,显示已获取的所有POI数据。
  12. 循环回到第5步,继续获取下一页的数据,直到没有更多数据可获取。
  13. 最后,返回包含所有获取到的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文件。

  1. 通过 load_workbook 函数从指定的Excel文件中加载工作表,该Excel文件位于路径 “D:/Desktop/1.xlsx”。
  2. 初始化一个空列表 classes 用于存储品牌名称。
  3. 使用 for 循环遍历Excel文件中第一个工作表 (sheets[0]) 的第一列数据(列’A’),并将品牌名称添加到 classes 列表中。注意,代码排除了第一行的标题行 “品牌名称”。
  4. 创建一个新的Excel工作簿对象 book,并创建一个新的工作表 sheet,将其插入到工作簿的第一个位置。
  5. 初始化计数器 count,用于跟踪写入的数据行数。
  6. 使用一个外层的 for 循环,遍历品牌名称列表 classes 中的每个品牌。
  7. 在每个循环迭代中,初始化一个空列表 classes_all_pois 用于存储与该品牌相关的所有POI数据。
  8. 调用 getcity(clas) 函数,获取与品牌相关的城市列表 city
  9. 使用一个内层的 for 循环,遍历城市列表 city 中的每个城市名称,并调用 getpois(cityname, clas) 函数获取该城市中与品牌相关的POI数据,并将其添加到 classes_all_pois 列表中。
  10. 输出当前城区、品牌名称以及获取到的POI数据的总数。
  11. 调用 write_to_excel(classes_all_pois, clas, count) 函数,将获取到的POI数据写入Excel文件中,该函数的定义在代码中没有提供,可能用于将数据写入Excel。
  12. 更新计数器 count,以反映已写入的数据行数。
  13. 输出所有城区的数据汇总,以及品牌名称写入成功的消息。

这段代码依赖于其他函数 getcitygetpoiswrite_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) + "写入成功")