爬取百度地图 POI 数据

爬取百度地图 POI 数据

初衷

老婆大人想知道金华地区的早教、培训机构相关的情况,老办法,爬起来。

百度地图api的限制

webapi/guide/webservice-placeapi – Wiki

查找了下大家获取百度POI数据的方法,知道了百度地图的地点检索api做了几个限制:

  • 非认证个人开发者2k每日请求量,认证后个人开发者3w日请求量
  • 检索接口最大返回670条结果 地点检索api分两类接口,一类是区域检索,第二类是详情检索,也就是说,如果我需要对每个地点去做详情检索,那就算3w的日请求量也远远不够了。好在我看区域检索接口内也可以返回较为详细的内容,基本够用。还有一个坑是区域检索接口是分页返回的,每页最多20条,所以这会消耗请求量。这里不考虑这些限制,大不了多跑几天。

实施方法

由于检索接口一次最多能返回670条数据,所以有个策略就是使用矩形检索接口,将矩形区域缩小到一定程度后,该区域的返回条目数不超过670条就可以,当然也不要太小,太小浪费请求量。

我先用一个大矩形划定我关心的区域,然后找到左上角和右下角的坐标:(这个可以手动从百度地图web站上获取到) 左下角,石门村:13312800.93,3357744.44 右上角,横山村:13334828.53,3373640.97

我们先设计10*10个小矩形来扫描。为了第二天继续爬取,每次移动记录当前矩形的位置。为了观察是否可能由于矩形过小导致数据丢失,记录每个矩形的获取数目,当等于670条时,可以重新细分扫描该类矩形区域。

注意 :上面拿到的坐标是百度地图米制坐标,需要转换成百度经纬度坐标才能用于检索api,转换api地址:webapi/guide/changeposition – Wiki

编码

由于是纯api爬取,就不上框架了。

#coding: utf-8
import requests
import json
import time


""" 查询关键字: """
FileKey = 'preclass'
KeyWord = u"早教$培训"

""" 关注区域的左下角和右上角百度地图坐标(经纬度) """
BigRect = {
    'left': {
        'x': 119.58962425017401,
        'y': 29.02371358317696
    },
    'right': {
        'x': 119.787499394624553,
        'y': 29.149153586357146
    }
}

""" 定义细分窗口的数量,横向X * 纵向Y """
WindowSize = {
    'xNum': 10.0,
    'yNum': 10.0
}


def getBaiduApiAk():
    """ 获取配置文件中百度apikey: { "baiduak":"xx"} :return: str """
    with open("./config.json", "r") as f:
        config = json.load(f)
        return config["baiduak"]

def getSmallRect(bigRect, windowSize, windowIndex):
    """ 获取小矩形的左上角和右下角坐标字符串(百度坐标系) :param bigRect: 关注区域坐标信息 :param windowSize: 细分窗口数量信息 :param windowIndex: Z型扫描的小矩形索引号 :return: lat,lng,lat,lng """
    offset_x = (bigRect['right']['x'] - bigRect['left']['x'])/windowSize['xNum']
    offset_y = (bigRect['right']['y'] - bigRect['left']['y'])/windowSize['yNum']
    left_x = bigRect['left']['x'] + offset_x * (windowIndex % windowSize['xNum'])
    left_y = bigRect['left']['y'] + offset_y * (windowIndex // windowSize['yNum'])
    right_x = (left_x + offset_x)
    right_y = (left_y + offset_y)
    return str(left_y) + ',' + str(left_x) + ',' + str(right_y) + ',' + str(right_x)


def requestBaiduApi(keyWords, smallRect, baiduAk, index, fileKey):
    today = time.strftime("%Y-%m-%d")
    pageNum = 0
    logfile = open("./log/" + fileKey + "-" + today + ".log", 'a+', encoding='utf-8')
    file = open("./result/" + fileKey + "-" + today + ".txt", 'a+', encoding='utf-8')
    # print('-------------')
    # print(index)
    while True:
        try:
            URL = "http://api.map.baidu.com/place/v2/search?query=" + keyWords + \
                "&bounds=" + smallRect + \
                "&output=json" +  \
                "&ak=" + baiduAk + \
                "&scope=2" + \
                "&page_size=20" + \
                "&page_num=" + str(pageNum)
            # print(pageNum)
            # print(URL)
            resp = requests.get(URL)
            res = json.loads(resp.text)
            # print(resp.text.strip())
            if len(res['results']) == 0:
                logfile.writelines(time.strftime("%Y%m%d%H%M%S") + " stop " + str(index) + " " + smallRect + " " + str(pageNum) + '\n')
                break
            else:
                for r in res['results']:
                    # print(r)
                    file.writelines(str(r).strip() + '\n')
            pageNum += 1
            time.sleep(1)
        except:
            print("except")
            logfile.writelines(time.strftime("%Y%m%d%H%M%S") + " except "  + str(index) + " " + smallRect + " " + str(pageNum) + '\n')
            break


def main():
    baiduAk = getBaiduApiAk()
    for index in range(int(WindowSize['xNum'] * WindowSize['yNum'])):
        smallRect = getSmallRect(BigRect, WindowSize, index)
        requestBaiduApi(keyWords=KeyWord, smallRect=smallRect, baiduAk=baiduAk, index=index, fileKey=FileKey)
        time.sleep(1)


if __name__ == '__main__':
    main()

复制代码

结果

发现我的需求,只要10*10就已经够用了。其实可以通过配置变量,查询想要查询的任何内容了。哔哔哔。。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/101456.html原文链接:https://javaforall.net

(0)
上一篇 2021年6月11日 下午9:00
下一篇 2021年6月11日 下午10:00


相关推荐

  • matlab imfilter函数图像(二维) opencv C++实现

    matlab imfilter函数图像(二维) opencv C++实现g imfilter f w filtering mode boundary options size options 默认是相关操作 填充为 0 大小形同 same 即如下效果相同 matlab kernel fspecial gaussian 10 5 img2 imfilter img1 kernel img3 imfilter img1 k

    2026年3月17日
    2
  • Retinex图像增强算法

    Retinex图像增强算法nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp Retinex 图像增强算法 nbsp Retinex 是一种常用的建立在科学实验和科学分析基础上的图像增强方法 它是 Edwin H Land 于 1963 年提出的 就跟 Matlab 是由 Matrix 和 Laboratory 合成的一样 Retinex 也是由两个单词合成的一个词语 他们分别是 retina 和 cortex 即 视

    2026年3月20日
    2
  • JSTL —[什么是JSTL,JSTL标签]

    JSTL —[什么是JSTL,JSTL标签]文章目录什么是 JSTLJSTL 环境搭建什么是 JSTLJSP 标准标识库 使用 JSTL 可实现 JSP 页面的逻辑处理 可用于编写各种动态 JSP 页面 JSTL Javaserverpa 即 JSP 标准标签库 是由 JCP Javacommunit 所制定的标准规范 它主要提供给 JavaWeb 开发人员一个标准通用的标签库 并由 Apache 的 Jakarta 小组来维护 开发人员可以利用这些标签取代 JSP 页面上的 Java 代码 从而提高程序的可

    2026年3月17日
    2
  • QXDM 安装[通俗易懂]

    QXDM 安装[通俗易懂]http://download.microsoft.com/download/5/6/7/567758a3-759e-473e-bf8f-52154438565a/dotnetfx.exe

    2022年10月3日
    4
  • Java安全之URLDNS链

    Java安全之URLDNS链0x00前言在学习Java的反序列化漏洞的时候,就不得不学习他的一个利用链。很多刚刚入门的对于利用链这个词可能比较陌生。那么这里先来了解一下Java反序列化和反序列化

    2021年12月12日
    50
  • 数据库索引的作用和长处缺点

    数据库索引的作用和长处缺点

    2021年12月6日
    49

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号