欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

公交站点信息爬虫

程序员文章站 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了

开始动手

  1. 登录百度地图开放平台,选择开发文档中的web服务api
    公交站点信息爬虫
  2. api左侧为功能区,点击不同的功能区,右侧有详细解释,具体的接口使用方法在右侧的服务文档中,输入参数和输出参数都有详细解释。
    公交站点信息爬虫
  3. 通过api接口,我们已经可以得到返回的json数据格式的公交站点信息,想要在程序中得到数据,并解析到公交站点,我们需要引入前面准备的3个python的库
    requests:利用url获取返回到的json数据
    json:解析json数据
    pymysql:用于存储到mysql数据库中(也可以不用,直接存到txt文档中)
import requests
import json
import pymysql
import time
  1. 本次爬虫采用矩形框搜索,需要定义矩形框的左下角坐标和右上角坐标,由于区域较大,可以将其分割成为多个区域.
    left_bottom = [106.283337,29.263947];  # 设置区域左下角坐标(百度坐标系)
    right_top = [106.753618,29.760811]; # 设置区域右上角坐标(百度坐标系)
    part_n = 10;  # 设置区域网格(10*10)
  1. 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信令
  1. 设置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);
  1. 记得每爬去一次就要休息一秒钟,百度不允许我们太快的爬取数据,会对其网站造成很大影响。
    time.sleep(1)
  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'])
  1. 如果想放入数据库中,可以调用这个函数,记得修改成你的数据库名和密码.
    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()
  1. 爬取公交站点完成,以下是爬取到的数据
    公交站点信息爬虫

  中间可能有些小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()
相关标签: 爬虫