公交站点信息爬虫
程序员文章站
2022-03-07 19:53:31
...
任务介绍
无论是工作的需要,还是业余时间想对网上数据进行分析,爬虫都是我们必须过的一个基本关。本次任务就是在工作需要的基础上,需要我们对整个XX市的公交站点进行爬取,获取其经纬度信息,便于后续数据的OD分析。按理说这个数据应该是公交公司有的,但是历史数据信息涵盖量不全,便寄希望于百度地图能给我们提供更多的一点信息吧。话不多说,开始今天的简易爬虫教程。
工具准备
本次爬虫需要用到的工具:
- 软件:pycharm,anaconda3(python3.6),百度**,mysql数据库。
- python库:requests,requests,json,pymysql,time
百度api申请步骤:
1. 打开网页,输入百度地图开放平台,点击进入
2. 注册百度账号,并且滑动到页面最下方,点击申请**
3. 点击创建应用,应用类型选择浏览器端,其余信息可以随便填写,白名单填写*(英文半角)
4. 以上步骤变申请成功,查看应用,就有你所创建的应用ak了
开始动手
- 登录百度地图开放平台,选择开发文档中的web服务api
- api左侧为功能区,点击不同的功能区,右侧有详细解释,具体的接口使用方法在右侧的服务文档中,输入参数和输出参数都有详细解释。
- 通过api接口,我们已经可以得到返回的json数据格式的公交站点信息,想要在程序中得到数据,并解析到公交站点,我们需要引入前面准备的3个python的库
requests:利用url获取返回到的json数据
json:解析json数据
pymysql:用于存储到mysql数据库中(也可以不用,直接存到txt文档中)
import requests
import json
import pymysql
import time
- 本次爬虫采用矩形框搜索,需要定义矩形框的左下角坐标和右上角坐标,由于区域较大,可以将其分割成为多个区域.
left_bottom = [106.283337,29.263947]; # 设置区域左下角坐标(百度坐标系)
right_top = [106.753618,29.760811]; # 设置区域右上角坐标(百度坐标系)
part_n = 10; # 设置区域网格(10*10)
- url设置(前面api中可以得到url)、这里设置搜索关键字,ak采用前面申请的浏览器ak
url0 = 'http://api.map.baidu.com/place/v2/search?';
x_item = (right_top[0]-left_bottom[0])/part_n;
y_item = (right_top[1]-left_bottom[1])/part_n;
query = '公交站'; #搜索关键词设置
ak = '***********************'; #百度地图api信令
- 设置url的不同字段,利用requests.get,就可以得到json数据,通过response.read(),就可以读到里面的数据,利用json库,解析json数据格式,得到里面的详细内容
url = url0 + 'query=' + query + '&page_size=20&page_num=' + str(k) + '&scope=1&bounds=' + str(left_bottom_part[1]) + ',' + str(left_bottom_part[0]) + ','+str(right_top_part[1]) + ',' + str(right_top_part[0]) + '&output=json&ak=' + ak;
response=requests.get(url)
data=response.text
hjson = json.loads(data);
- 记得每爬去一次就要休息一秒钟,百度不允许我们太快的爬取数据,会对其网站造成很大影响。
time.sleep(1)
- 这是得到的每个字段,里面有站点名,经纬度,地址,详情和唯一标识码,write_to_file,就可以将内容写到txt文件中。
if hjson['message'] == 'ok':
results = hjson['results']
for m in range(len(results)): # 提取返回的结果
# write_to_file(results[m])
fileData['name'].append(results[m]['name'])
fileData['lat'].append(results[m]['location']['lat'])
fileData['lng'].append(results[m]['location']['lng'])
fileData['address'].append(results[m]['address'])
fileData['detail'].append(results[m]['detail'])
fileData['uid'].append(results[m]['uid'])
- 如果想放入数据库中,可以调用这个函数,记得修改成你的数据库名和密码.
def write_to_mysql(contents):
# 连接数据库
con = pymysql.Connect(
host='localhost',
port=3306,
user='root',
passwd='',
db='busstation',
charset='utf8')
cur = con.cursor()
try:
for i in range(len(contents['name'])):
sql = "insert into bus_station_info(name,lat,lng,address,detail,uid) values (%s,%s,%s,%s,%s,%s)"
cur.execute(sql, [contents['name'][i], contents['lat'][i],contents['lng'][i], contents['address'][i],
contents['detail'][i], contents['uid'][i]])
# print(sql,[contents['name'][i], contents['lat'][i], contents['lng'][i], contents['address'][i],\
# contents['detail'][i], contents['uid'][i]])
except Exception as e:
print('加载sql语句出错', e)
else:
con.commit()
print('事务处理成功', cur.rowcount)
finally:
cur.close()
con.close()
- 爬取公交站点完成,以下是爬取到的数据
中间可能有些小bug,导致收集到的数据大量重复,数据爬取不是很完整(可能与api开放的数据量有关),有待改进,但功能完成,能正常运行,以下是完整代码。
# -*- coding: utf-8 -*-
# Python 3.6
# 提取公交站点信息,并存储到文件和MySQL中
import requests
import json
import pymysql
import time
#从第373个切片就已经不允许爬了,调用api当天配额已经用光了
def main():
chipStart=373
left_bottom = [106.283337,29.263947]; # 设置区域左下角坐标(百度坐标系)
right_top = [106.753618,29.760811]; # 设置区域右上角坐标(百度坐标系)
part_n = 20; # 设置区域网格(2*2)
url0 = 'http://api.map.baidu.com/place/v2/search?';
x_item = (right_top[0]-left_bottom[0])/part_n;
y_item = (right_top[1]-left_bottom[1])/part_n;
query = '公交站'; #搜索关键词设置
ak = '********************'; #百度地图api信令
n = 0; # 切片计数器
for i in range(part_n):
for j in range(part_n):
n += 1
if n<=chipStart:
continue
left_bottom_part = [left_bottom[0]+i*x_item,left_bottom[1]+j*y_item]; # 切片的左下角坐标
right_top_part = [right_top[0]+i*x_item,right_top[1]+j*y_item]; # 切片的右上角坐标
fileData={
'name':[],
'lat':[],
'lng':[],
'address':[],
'detail':[],
'uid':[]
}
for k in range(20):
url = url0 + 'query=' + query + '&page_size=20&page_num=' + str(k) + '&scope=1&bounds=' + str(left_bottom_part[1]) + ',' + str(left_bottom_part[0]) + ','+str(right_top_part[1]) + ',' + str(right_top_part[0]) + '&output=json&ak=' + ak;
response=requests.get(url)
data=response.text
hjson = json.loads(data);
time.sleep(1)
if hjson['message'] == 'ok':
results = hjson['results']
for m in range(len(results)): # 提取返回的结果
# write_to_file(results[m])
fileData['name'].append(results[m]['name'])
fileData['lat'].append(results[m]['location']['lat'])
fileData['lng'].append(results[m]['location']['lng'])
fileData['address'].append(results[m]['address'])
fileData['detail'].append(results[m]['detail'])
fileData['uid'].append(results[m]['uid'])
# write_to_mysql(fileData)
print ('第',str(n),'个切片入库成功')
def write_to_file(content):
with open('busStation.txt', 'a', encoding='utf-8') as f:
f.write(json.dumps(content) + '\n')
f.close()
def write_to_mysql(contents):
# 连接数据库
con = pymysql.Connect(
host='localhost',
port=3306,
user='root',
passwd='',
db='busstation',
charset='utf8')
cur = con.cursor()
try:
for i in range(len(contents['name'])):
sql = "insert into bus_station_info(name,lat,lng,address,detail,uid) values (%s,%s,%s,%s,%s,%s)"
cur.execute(sql, [contents['name'][i], contents['lat'][i],contents['lng'][i], contents['address'][i],
contents['detail'][i], contents['uid'][i]])
except Exception as e:
print('加载sql语句出错', e)
else:
con.commit()
print('事务处理成功', cur.rowcount)
finally:
cur.close()
con.close()
if __name__ == '__main__':
main()
上一篇: php怎么把时间戳转换为年月日
下一篇: Keepalive 基础概要及简单示例