爬取百度地图 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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Qt 资料大全[通俗易懂]

    Qt 资料大全[通俗易懂]全网最强整理,Qt官网、编码风格、GitHub&Third-Party、社区论坛、博客、书籍等资源,应有尽有。

    2022年7月17日
    21
  • 学生选课系统数据库设计「建议收藏」

    学生选课系统数据库设计「建议收藏」1.1需求分析数据库是一种存储数据并对数据进行操作的工具。数据库的作用在于组织和表达信息,简而言之,数据库就是信息的集合。计算机的数据库可以分为两类:非关系数据库和关系数据库。关系数据库中包含了多个数据表的信息,数据库含有各个不同部分的术语,如记录、域等。SQLserver2005就是关系数据库开发工具,数据库能汇集各种信息以供查询、存储和检索。SQL的优点在于它集

    2022年10月15日
    0
  • 网页大作业代码自取[通俗易懂]

    网页大作业代码自取[通俗易懂]网页大作业(内有代码可免费自取) 为了便于大家自取,代码都写在一页上,本人还是建议大家通过外链样式来引入css,代码仅供学习,如有侵权联系删除。![主页效果展示](https://img-blog.csdnimg.cn/20210505002015238.jpeg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3hpb25nbGxpbmc=,size_1

    2022年9月24日
    0
  • 在win10安装pip

    在win10安装pip

    2022年2月20日
    43
  • VMware下载安装教程(虚拟机详细安装教程)

    前面给大家讲过了虚拟机VBox的安装,个人觉得还是没有VMware好用,因为VMware有快照功能,而VBox没有;所以今天就给大家说下VMware的安装,有很多细节方面需要注意,不然很可能安装失败,这里就说下15.5.2的安装。建议不要安装最新版,因为我安装最新版的时候出现了一个情况,就是启动的时候要管理员身份才能打开,而且一直会停留在黑界面,进入不了设置界面,经过多个版本的尝试后,发现还是15.5.2版本的没有出现上述情况。虚拟机的安装1.进入VMware官网,点击左侧导航栏中的下载,再点击图中标

    2022年4月15日
    187
  • python安装dlib库_pycharm安装dlib失败

    python安装dlib库_pycharm安装dlib失败dlib库可以实现人脸的检测,所以有些小伙伴在学习人脸识别和检测的时候有可能会用到此库。本人python版本为3.7,在dlib的下载官网上只找到python3.6的版本,当然还有很多文章上写的是安装cmake进行编译再安装boost然后再使用pipinstalldlib安装即可,但是本人试了很多还是不行。3.7版本的dlib资源文件在csdn的其它文章中就有,淘宝0.5元即可下载,下载完成后将文件放置python文件下的Scripts文件夹中即可,结果如图。然后启动cmd,使用pipinstall

    2022年8月27日
    1

发表回复

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

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