python爬⾍爬取百度地图数据(百度API)转载
百度地图提供了丰富的api供开发者调⽤。我们可以免费获取各类地点的具体信息。
本次使⽤百度地图api获取数据,采⽤到的技术如下:
1.爬取⽹页:使⽤requests请求百度地图api地址
2.解析⽹页:提取json数据
3.存储数据:存储⾄MySQL数据库
1项⽬描述
本项⽬的⽬标是,通过百度地图web服务api获取中国所有城市的公园数据,并获取每⼀个公园具体评分、描述等详细内容,最终将数据存储到MySQL数据库。
⽹络爬⾍除了进⼊⽹站⽹页爬取外还可以通过⽹站提供的api进⾏爬取,由于api是官⽅提供的获取数据通道,所以数据的获取没有争议,如果⼀个⽹站提供api获取数据,最好使⽤api进⾏数据获取,简单⼜便捷。
除了百度地图外,其他国内提供api免费获取数据的站点还有新浪微博,⾖瓣电影,饿了吗,⾖瓣⾳乐等等,国外提供api服务的有Facebook,Twitter等。除此之外,还有很多收费的api数据站点服务,包括百度 api store 和聚合数据等。其他可以搜索⼀下就有了。
2获取api秘钥
填写好应⽤名称,选择使⽤ip⽩名单校验⽅式进⾏校验。在ip⽩名单的⽂本框中填写0.0.0.0/0,表⽰不对ip做任何限制。单机提交,即可在api控制台看到⾃⼰创建的AK,就是api请求串的必填参数。
有⼀点注意的是,未认证(个⼈或企业)的情况下,每个账号⼀天最多只有2000次调⽤额,如果认证了,每个账号每天有10万次调⽤额。
3 项⽬实施
本次项⽬实施主要分为三步:
1.获取所有拥有公园的城市,并将数据存储到txt⽂本中。
2.获取所有城市的公园数据,并将数据存储到MySQL数据库中。
3.获取所有公园的详细信息,并将数据存储到MySQL数据库中。
请求参数,设置如下(具体查看链接):
下⾯尝试获取北京市的公园数据,并⽤json数据格式返回,代码如下:
# coding=utf-8
import requests
import json
'''
获取北京市的公园数据,并⽤json数据格式返回
'''
def get_json(region):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16'
}
params = {
'query': '公园', #检索关键字
'region': region, #检索⾏政区划区域
'output': 'json', #输出格式为json
'scope': '2', #检索结果详细程度。取值为1 或空,则返回基本信息;取值为2,返回检索POI详细信息
'page_size': 20, #单次召回POI数量,默认为10条记录,最⼤返回20条。
'page_num': 0, #分页页码,默认为0,0代表第⼀页,1代表第⼆页,以此类推。
'ak': 'Kcl9bynY5Icf1yGv6mQPzS7Phhkuw0Pb'
}
res = ("api.map.baidu/place/v2/search", params=params, headers=headers)
content =
decodejson = json.loads(content) #将已编码的 JSON 字符串解码为 Python 对象,就是python解码json对象
#return decodejson
print(decodejson)
get_json("北京市")
输出结果为:
3.1 获取所有拥有公园的城市
接下来我们获取所有拥有公园的城市,并把数据存储到txt⽂本中。
在百度地图Place api,如果region的值为“全国”或则某个省份,则会返回指定区域的POI和数量。
我们可以把region设置为各个省份,进⽽获取各个省份各个市的公园数量。还有就是四⼤直辖市(北京、上海、天津、重庆)、⾹港特别⾏政区和澳门特别⾏政区,⼀个城市便是省级⾏政单位,因此regi
on设置的省份不包含这些特殊省级⾏政单位。
# coding=utf-8
import requests
import json
'''
获取所有拥有公园的城市,并把数据存储到txt⽂本中
'''
def get_json(region):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16'
}
params = {
'query': '公园', #检索关键字
'region': region, #检索⾏政区划区域
'output': 'json', #输出格式为json
'scope': '2', #检索结果详细程度。取值为1 或空,则返回基本信息;取值为2,返回检索POI详细信息
'page_size': 20, #单次召回POI数量,默认为10条记录,最⼤返回20条。
'page_num': 0, #分页页码,默认为0,0代表第⼀页,1代表第⼆页,以此类推。
'ak': 'Kcl9bynY5Icf1yGv6mQPzS7Phhkuw0Pb'
}
res = ("api.map.baidu/place/v2/search", params=params, headers=headers)
content =
decodejson = json.loads(content) #将已编码的 JSON 字符串解码为 Python 对象,就是python解码json对象
return decodejson
# print(decodejson)
# get_json("北京市")
province_list = ['江苏省', '浙江省', '⼴东省', '福建省', '⼭东省', '河南省', '河北省', '四川省', '辽宁省', '云南省',
'湖南省', '湖北省', '江西省', '安徽省', '⼭西省', '⼴西壮族⾃治区', '陕西省', '⿊龙江省', '内蒙古⾃治区',
'贵州省', '吉林省', '⽢肃省', '新疆维吾尔⾃治区', '海南省', '宁夏回族⾃治区', '青海省', '西藏⾃治区']
for eachprovince in province_list:
decodejson = get_json(eachprovince)
for eachcity in decodejson['results']:
city = eachcity['name']
num = eachcity['num']
content = '\t'.join([city,str(num)])+'\r\n'
with open('citys_','a+',encoding='utf-8') as f:
f.write(content)
f.close()
输出结果为:
接着,我们还要获取四个直辖市以及⾹港和澳门的数据,并把数据追加写⼊到citys_⽂本中。
# coding=utf-8
import requests
import json
'''
python请求并解析json数据获取所有拥有公园的城市,并把数据存储到txt⽂本中
'''
def get_json(region):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16'
}
params = {
'query': '公园', #检索关键字
'region': region, #检索⾏政区划区域
'output': 'json', #输出格式为json
'scope': '2', #检索结果详细程度。取值为1 或空,则返回基本信息;取值为2,返回检索POI详细信息
'page_size': 20, #单次召回POI数量,默认为10条记录,最⼤返回20条。
'page_num': 0, #分页页码,默认为0,0代表第⼀页,1代表第⼆页,以此类推。
'ak': 'Kcl9bynY5Icf1yGv6mQPzS7Phhkuw0Pb'
}
res = ("api.map.baidu/place/v2/search", params=params, headers=headers)
content =
decodejson = json.loads(content) #将已编码的 JSON 字符串解码为 Python 对象,就是python解码json对象
return decodejson
# print(decodejson)
# get_json("北京市")
decodejson = get_json('全国')
six_cities_list = ['北京市','上海市','重庆市','天津市','⾹港特别⾏政区','澳门特别⾏政区',]
for eachprovince in decodejson['results']:
city = eachprovince['name']
num = eachprovince['num']
if city in six_cities_list:
content = '\t'.join([city, str(num)]) + '\r\n'
with open('citys_', "a+", encoding='utf-8') as f:
f.write(content)
f.close()
输出结果为:
3.2 获取所有城市的公园数据
这次计划把公园的数据存储在MySQL数据库中,所以我们必须先创建⼀个badiumap数据库,⽤来存放所有公园爬去的数据。
创建⼀个数据库,语句为:create database baidumap;
当然也可以使⽤可视化⼯具创建数据库与完成⼀系列操作,如建表等。
蜂王胎冻干片哪些人不能吃然后就是建表了,在baidumap数据库中创建⼀个city表,⽤于存放所有城市的公园数据,公园的变量有:city,park,location_lng等等。这些变量就是第⼀部分测试的返回results中的数据,根据建⽴即可。
其中,为了避免数据存储重复,公园的详细信息会存储到另⼀个表中。
我们使⽤python的mysqlclient库来操作MySQL数据库,在baidumap数据库中建⽴city表。
# coding=utf-8
import MySQLdb
conn = t(host='localhost',user='root',password='123456',port=3306,db='baidumap')
cur=conn.cursor()
sql = """CREATE TABLE city (
id INT NOT NULL AUTO_INCREMENT,
city VARCHAR(200) NOT NULL,
input file美化park VARCHAR(200) NOT NULL,
location_lat FLOAT,
location_lng FLOAT,
address VARCHAR(200),
street_id VARCHAR(200),
uid VARCHAR(200),
created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
);"""
cur.close()
connmit()
conn.close()
接下来,爬取每个城市的公园数据,保存到city中。
# coding=utf-8
import requests
import json
import MySQLdb
'''
获取所有城市的公园数据
'''
conn = t(host='localhost',user='root',password='123456',port=3306,db='baidumap',charset="utf-8")
cur=conn.cursor()
# sql = """CREATE TABLE city (
# id INT NOT NULL AUTO_INCREMENT,
index与match函数# city VARCHAR(200) NOT NULL,
# park VARCHAR(200) NOT NULL,
# location_lat FLOAT,
# location_lng FLOAT,
# address VARCHAR(200),
# street_id VARCHAR(200),
# uid VARCHAR(200),
# created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
# PRIMARY KEY (id)
# );"""
# ute(sql)
# cur.close()
# connmit()
# conn.close()
def get_json(region,page_num):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16' }
params = {
'query': '公园', #检索关键字
'region': region, #检索⾏政区划区域
'output': 'json', #输出格式为json
'scope': '2', #检索结果详细程度。取值为1 或空,则返回基本信息;取值为2,返回检索POI详细信息
'page_size': 20, #单次召回POI数量,默认为10条记录,最⼤返回20条。
'page_num': 0, #分页页码,默认为0,0代表第⼀页,1代表第⼆页,以此类推。
'ak': 'Kcl9bynY5Icf1yGv6mQPzS7Phhkuw0Pb'
}
res = ("api.map.baidu/place/v2/search", params=params, headers=headers)
content =
decodejson = json.loads(content) #将已编码的 JSON 字符串解码为 Python 对象,就是python解码json对象
return decodejson
city_list=[]
with open('citys_','r',encoding='utf-8') as f:
# ad())
for eachLine in f:
if eachLine !="" and eachLine !="\n":
fields = eachLine.split("\t")
city=fields[0]
city_list.append(city)
#print(city_list)
for eachcity in city_list:
not_last_page = True
page_num = 0
while not_last_page:
decodejson = get_json(eachcity,page_num)
print(eachcity,page_num)
if decodejson['results']:
for eachone in decodejson['results']:
try:
park = eachone['name']
except:
park = None
try:
location_lat = eachone['location']['lat']
except:
location_lat = None
try:
location_lng = eachone['location']['lng']
except:
location_lng = None
try:
address = eachone['address']
except:
address = None
try:
street_id = eachone['street_id']
except:
street_id = None
try:
uid = eachone['uid']
z型钢梁价格except:
dictionary 变复数uid = None
sql = """INSERT INTO baidumap.city
(city, park, location_lat, location_lng, address, street_id, uid)
VALUES
(%s, %s, %s, %s, %s, %s, %s);"""
connmit()
page_num += 1
else:
not_last_page = False
cur.close()
conn.close()
在爬取过程中,遇到⼀个错误:
解决办法:
在上述代码中,⾸先从txt⽂件中获取城市列表,并加⼊city_list列表中,然后使⽤循环对每⼀个城市,每⼀页进⾏抓取,将获取数据⽤insert 的⽅法插⼊到baidumap数据库的city表中,注意到我是⽤了pt⽅法,主要是因为有些字段的值会空或则丢失,如有些公园没有街道id的,没有就赋予none值,防⽌程序保存。
共爬取了218941个公园信息,⼤概⽤了⼏分钟。
3.3 获取所有公园的详细信息
上⾯已经把所有城市的公园数据存储到city表中了。但是这些数据属于粗略的数据,接下来我们通过报读地图的Place详细检索服务获取每⼀个公园的详细信息。
例如,查询南京⽞武湖公园的详细信息,我们需要知道⽞武湖公园的uid,然后在请求地址中加上uid进⾏请求。
下⾯介绍下地点详细检索服务:
请求地址
请求参数以及返回参数(⾏政区划区域检索、圆形区域检索、矩形区域检索、地点详情检索)(详细见下链接):
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论