加载中…
个人资料
铁血阿郎map
铁血阿郎map
  • 博客等级:
  • 博客积分:0
  • 博客访问:6,726
  • 关注人气:1,970
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

零基础掌握百度地图兴趣点获取POI爬虫(python语言爬取)(进阶篇)

(2017-12-07 20:59:34)
标签:

python

教程

零基础

爬虫

arcgis

分类: 21世纪需要全才

我是怎么想的,在新浪博客里写代码教程。

这篇博客的内容同步到了CSND博客中,那里不限制外链,也可以复制代码。

http://blog.csdn.net/sinat_41310868/article/details/78746251



 

好,现在进入进阶篇教程。

1.获取昆明市的bounds

看到下面这个东西了吧?在文本框里写入昆明市,或者其他的行政区划地名,北京市、朝阳区、大河沟子村什么的。

这也是通过调用百度地图开放平台API实现的。

 http://s10/mw690/001oMyjxzy7goIITMJH59&690



实现起来很简单,把下面这段代码复制到一个txt文件中,然后把txt文件的拓展名改成html,用浏览器打开,就可以查询行政区划的范围了。

 

 

 

 

 

     

     

     

   

   

    添加行政区划 

 

 

 

   

 

   

 

       

 

        昆明市"/> 

        查看范围" id="commitBtn"/> 

        边界经纬度坐标 

         

        边界墨卡托坐标 

         

       

 

       

 

       

 

   

 

 

 

 

 

 

 

HTML是一个很神奇的格式,代码可以在文本文档里写,不过应该很少有人用文本文档写代码吧。

这段代码可以直接拿来用,也是我从网上找的,就不分析了。

 

2.更合理的对查询范围进行切分。

这是一个很常见的问题,我们要采集昆明市的中学兴趣点,然后就把矩形等分了六份,遍历一遍(其实要不遗漏的获取兴趣点,只切六个绝对不够用)。

这种切分方式其实并不完美,分析一下,中心城区兴趣点肯定分布更密集,而郊区会稀疏一些,而且一个城市的边界不可能是矩形的,我们用一个大矩形切分,会爬取到一些其他城市的兴趣点。

有相关从业经验的人应该能想到,如果有这个城市的分幅格网,遍历分幅格网来爬取兴趣点会更好一些,当然分幅格网我们也可以自己生成,根据预估的兴趣点疏密程度,中心城区格网加密一些,外围合并一些。

arcgis有一个工具fishnet(创建渔网),可以生成格网。

四至坐标可以在字段计算器里计算,选用python语言

minX=!shape.extent.xmin!

maxX=!shape.extent.xmax!

minY=!shape.extent.ymin!

maxY=!shape.extent.ymax!

之前写过一篇画分幅格网的教程:http://blog.sina.com.cn/s/blog_4c6ee7230102v590.html

 

arcgis属性表导出,可以用excel打开。

用这个坐标列表去生成url列表,主要就是openwrite语句的运用,其实都可以直接在excel里用函数去生成url列表。

python逐行读入:

f=open(路径,’a’)

f.readlines()

3.python中文乱码问题解决

其实这是一个很棘手的问题。对于初学者来说,遇到乱码问题,如何解决是一个幸运度的问题。有可能运气不好,就解决不了了,有可能运气够好,根本遇不上。

在乱码问题上,python2.7要多于python3

我精心挑选了几个我觉得讲得比较好的文章,大家可以参考一下,网上相关的文章太多了,容易懵。

这篇中文乱码的解决方式:

http://www.jb51.net/article/42707.htm

sys.getfilesystemencoding()获取文件系统的编码方式。

import sys

type = sys.getfilesystemencoding()

print mystr.decode('utf-8').encode(type)

这篇文章写得比较细:

http://blog.csdn.net/ggggiqnypgjg/article/details/53271541

 

我的经验是,如果遇到乱码,怎么都调试不成功,那么可以换一个编译环境,从python2.7换到python3,或者用别的函数,例如不用urllib2,用beautiful soul,或者requests等,有可能莫名其妙乱码的问题就不出现了呢!

 

4.并发量限制与延时功能

import time

time.sleep(10)

这两行代码的意思是,延时10秒中,它解决的是一分钟内并发量限制的问题,如果我们没有做认证,那么一分钟能访问API服务的次数不超过几次,超过了就会提示访问超过并发量,就爬不到数据了。

解决这个问题的方法就是用time.sleep(10),每次循环都先休眠10秒,就不会访问超过并发量了。

我觉得10秒够用了,所以就设定了10秒,不过如果认证过的开发者,应该不会遇到并发量限制的问题。

这段代码示例一下:

import time

time.sleep(10)

print time.time()

休眠十秒,打印当前时间,结果是一个浮点秒数。

5.把代码移植到python3中。

python2.7python3略微有些差异,python3版本有一个好处就是中文乱码的情况没那么多,而且很多功能和第三方库都被整合了。

下面这段代码是python3中的,可以看出比较于python2.7版本,进行了几处改变,requests、列表的引用等。

#-*-coding:UTF-8-*-

import json

import sys

import requests  #导入requests库,这是一个第三方库,把网页上的内容爬下来用的

ty=sys.getfilesystemencoding()  #这个可以获取文件系统的编码形式

import time

lat_1=24.390894

lon_1=102.174112

lat_2=26.548645

lon_2=103.678942   #坐标范围

las=1  #las一个值1

ak='9s5GSYZsWbMaFU8Ps2V2VWvDlDlqGaaO'

push=r'D:\python\zwzwlast.txt'

#我们把变量都放在前面,后面就不涉及到变量了,如果要爬取别的POI,修改这几个变量就可以了,不用改代码了。

 

 

print (time.time())  #相较于python2.7,python3print 需要加括号。

print ('开始')

urls=[] 声明一个数组列表

lat_count=int((lat_2-lat_1)/las+1)

lon_count=int((lon_2-lon_1)/las+1)

for lat_c in range(0,lat_count):

    lat_b1=lat_1+las*lat_c

    for lon_c in range(0,lon_count):

        lon_b1=lon_1+las*lon_c

        for i in range(0,20):

            page_num=str(i)

            url='http://api.ma/place/v2/search?query=中学& bounds='+str(lat_b1)+','+str(lon_b1)+','+str(lat_b1+las)+','+str(lon_b1+las)+'&page_size=20&page_num='+str(page_num)+'&output=json&ak='+ak

            urls.append(url)

#urls.append(url)的意思是,将url添加入urls这个列表中。

 

f=open(r'D:\python\kunmingxuexiao.txt','a',encoding='utf-8')

 

print ('url列表读取完成')

 

for url in urls:

    time.sleep(10) #为了防止并发量报警,设置了一个10秒的休眠。

    html=requests.get(url)#获取网页信息

    data=html.json()#获取网页信息的json格式数据

    for item in data['results']:

        jname=item['name']

        jlat=item['location']['lat']

        jlon=item['location']['lng']

        jadd=item['address']

        j_str=jname+','+str(jlat)+','+str(jlon)+','+jadd+'\n'

        f.write(j_str)

    print (time.time())

f.close()

print ('完成')   

 

 

6.代码简化问题。

可以通过分析json数据提炼一下简化方式。

网页打开之后,看一下。

{

    "status":0,

    "message":"ok",

    "total":400,

    "results":[

        {

            "name":"北大附中云南实验学校",

            "location":{

                "lat":25.009573,

                "lng":102.723208

            },

            "address":"昆明市日新中路北大附中云南实验学校",

            "street_id":"beabdbf4ac3394997069d3c7",

            "detail":1,

            "uid":"beabdbf4ac3394997069d3c7"

主要看results上面那三行,其中total,是这个矩形范围内有多少个兴趣点,有400个,说明我矩形画大了,应该再细分一下,这个数应该小于400,因为我们之前已经说过20页网址最多爬400poitotal400,说明实际的poi数量是大于400个的。

提取某一坐标范围中第一页数据的时候,我们可以先获取total值,这样就可以计算出page_num的值了,如果total100,那么只循环到第五页,page_num=4的时候就可以了。

这是代码的一个简化方式。

当然应该还有很多,有待我们发觉。

 

7.过程参考资料汇总

因为使用python的人很多,所以网上的资料也很多,不过要找到比较合适的,也没那么容易。但是说实话,走弯路、排除错误答案也是学习收获的一个过程,实践过错的,才知道什么是对的嘛!

最有用的参考资料,还得是是官网。

https://www.python.org/

学好英语很必要。

这个网址,讲的是requests的用法。

http://docs.python-requests.org/zh_CN/latest/user/quickstart.html

当然,买本书应该也不错。

然后脚本之家和CSDN都有很好的教程,不过也不是所有教程都是对的,多看多试多思考多练习,就会有多获得。

最后会再来一篇python安装和第三方库安装篇,这个python的零基础教程就先告一段落吧!

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有