重磅!全站首发,新鲜出炉,1024特辑,手把手教你采集 高德地图 搜索结果,获取全国海底捞信息并可视化

高德地图是我们经常用的地图软件,今天我们以海底捞为例子,取全国的海底捞搜索结果为自己用!这里的方法只用于个人采集公开数据,请不要用于商业或违法用途!
因为整个C站还没有分享这方面技术的,所以我写一篇给大家节日助助兴!喜欢的大哥大姐们给我点点关注点点赞~
项目公开地址:

https://codechina.csdn.net/sabian2/haidilao.git

可以直接clone到本地
在这里插入图片描述

工具

编程软件:Pycharm
Python版本:3.7.6
浏览器:双核浏览器
依赖库:urllib,requests,json,pymysql
分析工具:Postman

分析网页获取第一个接口

首先进入高德地图,搜索范围地选全国,然后F12检查,进入网络(network)界面,在搜索框输入‘海底捞’,先不点搜索按钮,清空网络界面的数据,再点击,此时的界面一般是这样的,

在这里插入图片描述
逐个点击右侧像数据接口的网页,发现第一个下划线的东西,返回的数据中存有左侧搜索结果的城市信息
在这里插入图片描述看直辖市上海,城市名和搜索结果数都能对应,很显然,这将是我们取得的第一层数据。
根据生活经验,对照上张图片的搜索结果,容易得出,areacode是地区电话号码的区号,ename是地区英文名称,adcode是邮编,total是地区的海底捞搜索结果数,name是地区中文名称
由于这里的数据有200多条,后续的数据更多,所以这里建立数据库存储,把这个数据存放在city表

创建第一个数据库表

city表的创建语句

sql1='''
CREATE TABLE IF NOT EXISTS `city` (
  `adcode` VARCHAR(6) NOT NULL DEFAULT '邮政编码' COMMENT '邮政编码',
  `areacode` VARCHAR(6) NOT NULL DEFAULT '电话区号' COMMENT '电话区号',
  `name` VARCHAR(45) NOT NULL DEFAULT '城市名称' COMMENT '城市名称',
  `ename` VARCHAR(45) NOT NULL DEFAULT '城市英文名称' COMMENT '城市英文名称',
  `total` INT NOT NULL DEFAULT 0 COMMENT '数量',
  PRIMARY KEY (`adcode`))
ENGINE = InnoDB
COMMENT = '城市信息';
'''

postman测试接口的请求参数

通过postman测试这个接口要什么请求头参数才能获得
在这里插入图片描述
直接获取显然是不行的
在这里插入图片描述
再尝试发现加上UA和cookies就可以了
在这里插入图片描述

保存接口响应的数据

直接用postman生成python代码,取得这个数据保存到文件里,或者直接复制postman下面的数据保存到文件里即可

import requests

url = "https://www.amap.com/service/poiInfo?query_type=TQUERY&pagesize=20&pagenum=1&qii=true&cluster_state=5&need_utd=true&utd_sceneid=1000&div=PC1000&addr_poi_merge=true&is_classify=true&zoom=4&city=100000&geoobj=109.337074%7C22.883865%7C151.524574%7C55.107505&keywords=%E6%B5%B7%E5%BA%95%E6%8D%9E"

payload={}
headers = {
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36',
  'Cookie': 'cna=oAf1GYRz1i8CAd9CwvtddGMZ; UM_distinctid=17ca72d57e1483-0f1c7a9cb0dbbe-3e604809-100200-17ca72d57e253e; _uab_collina=163489234130013489187538; xlly_s=1; passport_login=NzQ0NzcwNTc0LGFtYXBfMTc3MDE3MjA2MTNDanEzRG9SV3IsYWVsdzZqcWI0N3dmcXFieDI3dXBjZmh5aW5icGtvd3ksMTYzNDk4MTMzOCxOMlF6WVdFd01XWXpPV0UxWVdVMU5EQmtZMk5pWldVelpEZzRNREJtTkdZPQ%3D%3D; guid=0779-0b27-044d-88f0; CNZZDATA1255626299=1457747375-1634883830-https%253A%252F%252Fwww.baidu.com%252F%7C1635035171; x5sec=7b227761676272696467652d616c69626162612d616d61703b32223a223863376433376639643564383833336662363934656531653864333364303739434f2f73306f7347454c75387434443132715767677745773370656271514d3d227d; x-csrf-token=5cb578d04186b6ce4edbf05f5f27156d; tfstk=cqkGBg6vCfP_rPNnNdwsAeg-xNAGaqIa57FELYxRLiq8VHDUbsAVT_rJ8NaF4N5f.; l=eBauGa7ng1lUhZ5MBO5aourza779oIRfG-VzaNbMiInca6M1vFNCXNCLyI8kBdtjgtCfhUxPkdi_7RHBJBzdg5n8-lA1tTf7NxJO.; isg=BAUFUVadyPDFXOyqDS4SiIyzFEE_wrlUzh-b8QdqRTxLniEQxRIrJLs4qMJo5NEM'
}

response = requests.request("GET", url, headers=headers, data=payload)

with open('citydata.txt','w') as f:
    print(response.text)
    f.write(response.text)

将响应数据存入数据库

用json读取这个文件,取得第一层城市信息数据,存入数据库中

import json
with open('citydata.txt','r') as f:
    jsondata=json.load(f)
regions=jsondata.get('data').get('suggestion').get('regions')
for region in regions:
    sql2=f"""insert into `city`  (`areacode`,`adcode`,`name`,`ename`,`total`) value ('{region['areacode']}','{region['adcode']}','{region['name']}',"{region['ename']}",'{region['total']}');"""
    try:
        rows=cursor.execute(sql2)
    except:
        print(sql2+"\n语句执行失败")
        continue
    client.commit()

分析网页获取第二类接口

现在我们已经取得了第一张表,接下来查看城市里面的结果是如何显示的,从左侧城市结果里面点击广东进入广州市,还是找新的接口,和前面的接口名字差不多
在这里插入图片描述
但是广州的数据不止这界面的20条,20条是被查询参数限制的,所以要修改查询参数
在这里插入图片描述
还是通过postman做尝试,一旦postman尝试出错就要跑到浏览器里面重新打开高德进行滑块验证

在这里插入图片描述

分析网址

https://www.amap.com/service/poiInfo?query_type=TQUERY&pagesize=20&pagenum=1&qii=true&cluster_state=5&need_utd=true&utd_sceneid=1000&div=PC1000&addr_poi_merge=true&is_classify=true&zoom=9.34&city=320000&geoobj=118.287654%7C31.470088%7C119.325966%7C32.364258&keywords=%E6%B5%B7%E5%BA%95%E6%8D%9E
这是浏览器中取得的南京地区的搜索结果接口地址,里面参数很多
对比广州,utd_sceneid参数是不一样的,这个参数值并不清楚怎么取得,尝试修改参数或者去掉这个参数,发现是可以的
在这里插入图片描述
放到postman里面,改need_utd 为false,去掉utd_sceneid参数,还是可以正常获取

在这里插入图片描述
这里发现南京的city是320000,但数据库存的是320100,这样没法自动化,尝试修改看看。
在这里插入图片描述
发现还是可以正常获取数据的
在这里插入图片描述

接着把经纬度geoobj去掉看看
在这里插入图片描述
结果顺序好像是不一样的,内容没问题

剩下的可能只要把pagesize改为总数即可获取全部
现在的半纯净地址是

https://www.amap.com/service/poiInfo?query_type=TQUERY&qii=true&cluster_state=5&need_utd=false&div=PC1000&addr_poi_merge=true&is_classify=true&zoom=4&city=320100&keywords=%E6%B5%B7%E5%BA%95%E6%8D%9E&pagesize=20&pagenum=1

提取里面的pagesize和city作为我们要调整的循环变量,在数据库中读出

## 数据库读取关键参数

sql3='select adcode,total from `city`'
cursor.execute(sql3)
data=cursor.fetchall()
# print(data)-》》(('110000', 255), ('120000', 122), ('130100', 31),

## 数据库关键参数读取结束

经过测试,一次性读取的最大值是30,给他再打的pagesize都不会改变一个页面最多30条,所以要分页多次读取,为了伪装,我们还是选用默认的20个作为参数,调整分页页面的值

在这里插入图片描述

获取数据,存到文件

读取过程中,可以发现,其实是没有第一层搜索里显示的这么多数据的,搜索结果内部的比如北京255,保存的数据只有6页,120多个,网页上点进去其实也是这个结果,获取的数据量应该还算完整
在这里插入图片描述

又比如在这个地区的搜索框是有一个海底捞结果的,但是这个店本身也不是海底捞,在查询接口时会被过滤掉,所以第一层里面的存储total其实不起作用。把程序中的分页逻辑调整为检查数据中是不是包含“未找到”。
在这里插入图片描述

Cookie失效的处理

基本上一个新的cookie用到一半左右,会出现错误,要自己去网页端验证一下,拿到新的cookie,这可能是服务器存的数据改变引起的,cookie本身的时间是很长的,最早过期的都要到第二天。
在这里插入图片描述
在这里插入图片描述

请求各城市数据接口的代码

# ## 从网页读取各城市数据
#
headers = {
  'Cookie': 'cna=oAf1GYRz1i8CAd9CwvtddGMZ; UM_distinctid=17ca72d57e1483-0f1c7a9cb0dbbe-3e604809-100200-17ca72d57e253e; _uab_collina=163489234130013489187538; xlly_s=1; passport_login=NzQ0NzcwNTc0LGFtYXBfMTc3MDE3MjA2MTNDanEzRG9SV3IsYWVsdzZqcWI0N3dmcXFieDI3dXBjZmh5aW5icGtvd3ksMTYzNDk4MTMzOCxOMlF6WVdFd01XWXpPV0UxWVdVMU5EQmtZMk5pWldVelpEZzRNREJtTkdZPQ%3D%3D; guid=f0d3-cf05-bf77-9378; CNZZDATA1255626299=1457747375-1634883830-https%253A%252F%252Fwww.baidu.com%252F%7C1635045974; x-csrf-token=f4ebc0f94d2b80fe0fb5220728c910e1; x5sec=7b227761676272696467652d616c69626162612d616d61703b32223a223035353835376531353438323533353339643038343163336438373463643961434b544e303473474549726f714d4c7737347939667a44656c35757041773d3d227d; tfstk=c7_1BNiC1AD1Pbrq71NE3UdWCsvcaT3Bt2vF1i1x2Jbsf5fwpsDjzLZDkCMCcKAC.; l=eBauGa7ng1lUhlR3BO5Zlurza77OiIdf5CVzaNbMiInca6gGYFtjBNCLytP9QdtxgtCfWe-Pkdi_7RFyJFUdg5n8-lA1tTf7TxJO.; isg=BFtbTWMKvpa_scLkR_wEblah6r_FMG8ypC01v02ZutpxLHIO1gBGgmfqx4yiI8cq',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'
}
error_msg = '哎哟喂,被挤爆啦,请稍后重试'
end_msg ='未找到'
for i in data:
    total = 1
    adcode = i[0]
    while True:
        status = 200

        url=f'https://www.amap.com/service/poiInfo?query_type=TQUERY&qii=true&cluster_state=5&need_utd=false&div=PC1000&addr_poi_merge=true&is_classify=true&zoom=4&city={adcode}&keywords=%E6%B5%B7%E5%BA%95%E6%8D%9E&pagesize=20&pagenum={total}'

        print(url)
        # exit()
        response = requests.request("GET", url, headers=headers).text
        ## 不要造成密集请求被屏蔽
        time.sleep(2)
        if error_msg in response:
            status=400
        while status!=200:
            headers['Cookie']=input('出现错误,请自行寻找cookie输入')
            response = requests.request("GET", url, headers=headers).text
            if error_msg in response:
                status = 400
            else:
                status=200

        if end_msg in response:
            break
        filename='data/'+adcode+f'-{total}'
        print(filename)
        with open(filename,'w',encoding='utf-8') as f:
            f.write(response)
        total+=1

## 城市数据写入完成

分析接口数据格式

每个店的参数在浏览器看到的有这些
在这里插入图片描述
我们从接口得到的也有许多前端没有渲染的数据
在这里插入图片描述

综合一下,我们根据文件里的名称提取以下数据
districtcode-地址的邮编,address-地址,provincename-省份,districtname-区名,cityname-城市名称,name-店名,id-元素的id,latitude-纬度,longitude-经度,src_star-评分,review_total-浏览量,tel-电话,business_area-商业区,opentime-开闭时间,averagecost-人均消费,pcdr-精确到路的地址,tag_display-菜品
同时在数据库表中保存城市的adcode,作为外键

建数据表语句

## 建数据表语句
createtable2="""
CREATE TABLE IF NOT EXISTS `result` (
  `id` varchar(10) NOT NULL COMMENT "网页id",
  `districtcode` varchar(6) NOT NULL DEFAULT "邮编" COMMENT "具体的邮编",
  `address` varchar(150) NOT NULL DEFAULT "地址" COMMENT "地址",
  `provincename` varchar(20) NOT NULL DEFAULT "省份名称" COMMENT "省份名称",
  `districtname` varchar(20) NOT NULL DEFAULT "区域名称" COMMENT "区域名称",
  `cityname` varchar(30) NOT NULL DEFAULT "城市名称" COMMENT "城市名称",
  `name` varchar(150) NOT NULL DEFAULT "店名" COMMENT "地址名称",
  `latitude` double NOT NULL DEFAULT "0" COMMENT "纬度",
  `longitude` double NOT NULL DEFAULT "0" COMMENT "经度",
  `src_star` double NOT NULL DEFAULT "0" COMMENT "评分",
  `review_total` INT NOT NULL DEFAULT "0" COMMENT "访问量",
  `tel` varchar(200) NOT NULL DEFAULT "电话号码" COMMENT "电话",
  `business_area` varchar(45) NOT NULL DEFAULT "商业区",
  `opentime` varchar(45) NOT NULL DEFAULT "开闭时间" COMMENT "开闭时间",
  `averagecost` float NOT NULL DEFAULT "0" COMMENT "人均",
  `pcdr` varchar(45) NOT NULL DEFAULT "精确到路的地址" COMMENT "精确到路的地址",
  `tag_display` varchar(250) DEFAULT "菜品" COMMENT "菜品",
  `adcode` varchar(6) NOT NULL DEFAULT "区域代码" COMMENT "区域代码",
  PRIMARY KEY (`id`),
  KEY `adcode_idx` (`adcode`),
  CONSTRAINT `adcode` FOREIGN KEY (`adcode`) REFERENCES `city` (`adcode`) ON DELETE CASCADE
)ENGINE = InnoDB
COMMENT="搜索结果";
"""
cursor.execute(createtable2)
client.commit()

## 建数据表完成

提取关键字到数据库

提取文件数据到数据库中,这里提取过程中输出了数据,可以在出问题时看看是什么样的数据出问题了,对数据库和语句做调整
我这里修改了几次字段的大小之后,成功执行完毕
在这里插入图片描述


## 转换城市数据到数据库
dirlist=os.listdir('data')
for filename in dirlist:
    with open('data/'+filename,'r',encoding='utf-8') as f:
        jsondata=json.load(f)
        shuju=jsondata.get('data').get('poi_list')
        for table in shuju:
            id=table.get('id')
            districtcode=table.get('districtcode')
            address=table.get('address')
            provincename=table.get('provincename')
            districtname=table.get('districtname')
            cityname=table.get('cityname')
            name=table.get('name')
            latitude=table.get('latitude')
            if not latitude:
                latitude=0

            longitude=table.get('longitude')
            if not longitude:
                longitude=0
            src_star=table.get('src_star')
            if not src_star:
                src_star=0
            review_total=table.get('review_total')
            if not review_total:
                review_total=0
            tel=table.get('tel')
            business_area=table.get('business_area')
            opentime=table.get('opentime')
            averagecost=table.get('averagecost')
            if not averagecost:
                averagecost=0
            try:
                int(averagecost)
            except:
                print(averagecost)
                averagecost=0
            pcdr=table.get('pcdr')
            tag_display=table.get('tag_display')
            adcode=filename.split('-')[0]
            print(id, districtcode,        address,        provincename,        districtname,        cityname,        name,        latitude,
            longitude,        src_star,        review_total,        tel,        business_area,        opentime,        averagecost,
            pcdr,        tag_display,        adcode)
            sql4=f"insert into `result` (`id`, `districtcode`, `address`, `provincename`, `districtname`, `cityname`,  `name`, `latitude`,`longitude`, `src_star`, \
             `review_total`,  `tel`,   `business_area`,    `opentime`,  `averagecost`, `pcdr`, `tag_display`, `adcode`) value ('{id}', '{districtcode}','{address}',\
              '{provincename}','{districtname}',   '{cityname}',        '{name}',        '{latitude}', '{longitude}', '{src_star}',       \
               '{review_total}',        '{tel}',        '{business_area}',        '{opentime}',        '{averagecost}',     '{pcdr}',    \
                   '{tag_display}',        '{adcode}')"

            rows=cursor.execute(sql4)
            print(rows)


            client.commit()

结果

在全国共获取有效的海底捞店铺1954家!
在这里插入图片描述
数据的存储效果
在这里插入图片描述

拓展

这次我们查的是海底捞,每个城市不一定有海底捞,但一定都有学校、医院这种公共设施,这次的搜索结果表明第一层数据的total数据是没用的,所以我们完全可以直接从第二个链接开始。首先做一个数据表存储所有的城市邮编,然后就可以挨个检索。
海底捞是keywords参数
keywords=%E6%B5%B7%E5%BA%95%E6%8D%9E
后面的字段可以通过urllib的parse包的quote方法转换中文为这个字符串
在这里插入图片描述
据此可以搜索任意想要的关键字的结果。

文章到这里还没结束,我再拓展拓展可视化的操作,大家先给我点点赞,收藏收藏,鼓励鼓励

Powerbi的分析

工具

这里选用windows的powerbi做分析,版本就最新版,刚下载的还热乎着。如果你是windows7及以下版本,那你下载的时候看最后支持的版本,windows7在今年年初就不支持了,其他的更早。
数据表的读取直接从数据库连接即可,选更多,找到mysql,这里可能需要先安装一个mysql-connector-net-8.0.20.msi,如果你找不到,请留言,我给你发下载地址。
这里用到的功能并不复杂,低版本可能只是操作的位置不一样,其他都一样。

在这里插入图片描述

先看哪个省的海底捞最多

建立一个度量值
店铺数量 = COUNT(‘db2 result’[name])

在报表界面,建立一个矩阵,行依次放置省份名称,城市名称,街道名称,值放置店铺数量
在这里插入图片描述
展开的显示效果为
在这里插入图片描述
这是经过排序的,可以发现,广东省最多
去掉省,排序可以发现,上海最多,深圳市是排第一的 一个市级地区
在这里插入图片描述
以省级生成环形图看店铺的大致分布情况

在这里插入图片描述

看哪个地方搜索损失率最大

在市级层面可以看得到的结果和最初的搜索结果数的比率

新建度量值
搜索数量 = SUM(‘db2 city’[total])
损失率 = 1-[店铺数量]/[搜索数量]
这里需要将对应关系切换为city表name对应result表的cityname,外键关系切换为虚线,这个关系为实线
在这里插入图片描述

建一个表格,第一个name取的是city表的

在这里插入图片描述
可以看到有些地方直接就是没有的
在这里插入图片描述

如果要看省一级的,需要对数据进一步拆分,将省市区的对应关系单独建表
更多的视图自己探索啦~

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Amoor123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值