本篇博客内容主要引自:https://zhuanlan.zhihu.com/p/73712621,对该作者表示感谢。
需求:爬取某几个省的茶园POI数据
百度地图API爬虫注意事项:
1、通过行政区划进行数据爬虫,需要用市一级的行政规划,省级行政规划只能取到粗略值。
2、申请AK,需要进行开发者认证,否则会有下载并发限制。
3、可以把爬取结果存入excel,也可以放入mysql,我在存入mysql时,报1366的错误,这是因为在向数据库插入中文编码有错,需要更改表的字符编码,方法如下:
1)首先更改表的字符集编码
ALTER TABLE `tablename` DEFAULT CHARACTER SET utf8;
2)然后需要修改每个varchar字段的字符集编码
alter table tablename change column column varchar(xxx) character set utf8;
方法:
1、首先根据关键字和省份数据生成待爬取的城市列表信息,并存入TXT中。
# 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': ak # 需要自己申请ak http://lbsyun.baidu.com/apiconsole/key?application=key#/home
}
res = requests.get("http://api.map.baidu.com/place/v2/search", params=params, headers=headers)
content = res.text
decodejson = json.loads(content) #将已编码的 JSON 字符串解码为 Python 对象,就是python解码json对象
print(decodejson)
return decodejson
# 需要爬取的省份
province_list = ['江苏省', '浙江省', '广东省', '福建省', '山东省', '河南省', '四川省', '云南省',
'湖南省', '湖北省', '江西省', '安徽省', '广西壮族自治区', '陕西省',
'贵州省', '甘肃省', '海南省', '西藏自治区','台湾']
# 将爬取的城市列表写入txt
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_chayuan_num.txt','a+',encoding='utf-8') as f:
f.write(content)
f.close()
2、遍历TXT城市列表,对每个城市根据关键字进行数据爬取,并将爬取的所有信息存入mysql数据库中。
# 创建数据表
CREATE TABLE city (
id INT NOT NULL AUTO_INCREMENT,
city VARCHAR(200) NOT NULL,
chayuan 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)
);
# coding=utf-8
import requests
import json
import MySQLdb
import io
import sys
from urllib.request import urlopen
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8')
'''
获取城市列表中每个茶园数据
'''
conn = MySQLdb.connect(host='localhost',user='root',password='yourpassword',port=3306,db='db',charset="gbk")
cur=conn.cursor()
def get_json(region,page_num):
# print(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详细信息
'coord_type' : '1', #1表示WGS84坐标
'page_size': 20, #单次召回POI数量,默认为10条记录,最大返回20条。
'page_num': page_num, #分页页码,默认为0,0代表第一页,1代表第二页,以此类推。
'ak': 'ak'
}
res = requests.get("http://api.map.baidu.com/place/v2/search", params=params, headers=headers)
content = res.text
decodejson = json.loads(content) #将已编码的 JSON 字符串解码为 Python 对象,就是python解码json对象
return decodejson
city_list=[]
with open('citys_chayuan_num.txt','r',encoding='utf8') as f:
# print(f.read())
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)
if decodejson['results']:
for eachone in decodejson['results']:
try:
chayuan = eachone['name']
except:
chayuan = 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']
except:
uid = None
sql = """INSERT INTO swtgeo.chachang
(city, chayuan, location_lat, location_lng, address, street_id, uid)
VALUES
(%s, %s, %s, %s, %s, %s, %s);"""
cur.execute(sql,(eachcity, chayuan, location_lat, location_lng, address, street_id, uid,))
conn.commit()
page_num += 1
else:
not_last_page = False
cur.close()
conn.close()