当前位置: 首页 > 科技观察

我用Python爬取了全国4500个热门景区,告诉你国庆最堵的地方在哪里?

时间:2023-03-20 13:03:50 科技观察

九月金秋,桂花飘香。在这个秋高气爽、阳光明媚的收获季节,我们送走了暑假余额用尽、哭闹着奔向校园的孩子们,我们即将迎来一年一度的伟大祖国母亲生日会??(无心情为了工作,迫不及待地想在祖国给妈妈过生日)。那么问题来了,去哪里玩呢?百度丢了一个“国庆节”,出来的第一篇文章是“游客少去哪里玩”……emmmmmmm,因为没有思考的殿堂。于是萌生了通过旅游网站上的景点销量来判断各个景点近期人流量的想法(这个想法很危险)。所以这次的目标是爬上去哪儿网的景点页面,获取景点信息。你可以想想它需要多少步。本文推荐有一定Python基础和前端(html、js)基础的朋友阅读。没有基础的可以看看我之前的文章。(咳咳,总不能更小白文吧,看来我还不够(mei)够(you)专(xue)(xi))。前几次百度的地图API和echarts爬取了一些文字信息,做了词云之类的。我想:不行!意义!思维!这次恰好是爬取数据,所以我决定使用datagoodfriends—charts来输出我爬取的数据,也就是说我要用爬取的景区销量和景区的具体位置来生成一些视觉数据。看看百度的地图API和echarts。前者是提供地图API的工具。我听说很多应用程序都在使用它。后者是数据处理和居家旅行的好搭档。用了之后还不错,我也不错(隐约感觉哪里不对)。什么是API?API是应用程序的编程接口,就像插头和插座一样,我们的程序需要电(这是什么程序?),插座提供电,我们只需要在程序插件接口,我们可以用电来做我们想做的事情,而不知道它是如何产生的。数据引入后的百度热图。通过API连接的开发人员和服务提供商确定输出文件。可能有人会说,我已经明白API是什么意思了,但是怎么用呢。关于这一点,我很负责任的告诉你:我也不会。但是!百度地图提供了很多API的使用示例,有html基础的可以粗略看懂,有js基础的可以尝试改功能(不懂js的我就默默复制源码),仔细观察源码,可以知道热图生成的主要数据都存储在变量points中。这种[{x:x,x:x},{x:x,x:x}]格式的数据是一种json格式的数据。因为是自描述的,所以比较容易理解。你大概可以知道这里的三个值,前两个是纬度和经度,最后一个应该是权重(我猜的)。也就是说,如果我要生成景点的热度图,我需要获取景点的经纬度,以及它的权重,景点的销售额可以作为权重,而这个数据应以json格式呈现。echarts也是如此(*^__^*)。爬取数据这次的爬取部分比较简单。解析URL(去哪里的景点)→抓取页面中的信息(景点经纬度、销量)→转成json文件。分析去哪儿的景点页面的URL,我们可以得到结构:http://piao.qunar.com/ticket/list.htm?keyword=SearchPlace?ion=&from=mpl_search_suggest&page=页面数这次,正则表达式不习惯匹配内容,使用xpath匹配,非常好用。defgetList():place=raw_input('请输入您要搜索的地区和类型(如北京、热门景点等):')url='http://piao.qunar.com/ticket/list.htm?keyword='+str(place)+'®ion=&from=mpl_search_suggest&page={}'i=1sightlist=[]whilei:page=getPage(url.format(i))selector=etree.HTML(page)print'爬取页面'+str(i)+'页面景点信息'i+=1informations=selector.xpath('//div[@class="result_list"]/div')forinfininformations:#获取必要信息sight_name=inf.xpath('./div/div/h3/a/text()')[0]sight_level=inf.xpath('.//span[@class="level"]/text()')iflen(sight_level):sight_level=sight_level[0].replace('景区','')else:sight_level=0sight_area=inf.xpath('.//span[@class="area"]/a/text()')[0]sight_hot=信息。xpath('.//span[@class="product_star_level"]//span/text()')[0].replace('heat','')sight_add=inf.xpath('.//p[@class="addresscolor999"]/span/text()')[0]sight_add=re.sub('地址:|(.*?)|\(.*?\)|,.*?$|\/.*?$','',str(sight_add))sight_slogen=inf.xpath('.//div[@class="introcolor999"]/text()')[0]sight_price=inf.xpath('.//span[@class="sight_item_price"]/em/text()')iflen(sight_price):sight_price=sight_price[0]else:i=0breaksight_soldnum=inf。xpath('.//span[@class="hot_num"]/text()')[0]sight_url=inf.xpath('.//h3/a[@class="name"]/@href')[0]sightlist.append([sight_name,sight_level,sight_area,float(sight_price),int(sight_soldnum),float(sight_hot),sight_add.replace('address:',''),sight_slogen,sight_url])time.sleep(3)returnsightlist,place这里爬取了每个景点的所有信息(其实就是为了练习xpath的使用。。。)用到了while循环,for循环的break方法是当没有找到销售时,将零分配给i值。这样while循环也会同时结束。地址匹配使用re.sub()函数去除n个以上的复杂信息,后面会解释。输出本地文本为防止代码运行出错,维护代码运行的安宁,将输出信息列表保存在excel文件中,方便日后查阅。代码很简单,需要了解pandas的用法。deflistToExcel(list,name):df=pd.DataFrame(list,columns=['景点名称','等级','面积','起拍价','销售额','热度','地址','标语','详情网址'])df.to_excel(name+'景点信息.xlsx')百度的经纬度API很悲催,(?﹏?)我没有找到我去的景点的经纬度,我还以为这次学(zhuang)习(bi)计划要流产了。(谁知道景区的经纬度在哪里,请告诉我)但是,恩哈哈哈哈哈哈,我怎么能放弃呢,我又找到了百度经纬度API。网址:http://api.map.baidu.com/geocoder/v2/?address=address&output=json&ak=百度键,修改网址中的“地址”和“百度键”,在浏览器中打开,即可会看到经纬度的json信息。#上海东方明珠经纬度信息{"status":0,"result":{"location":{"lng":121.5064701060957,"lat":31.245341811634675},"precise":1,"confidence"":70,"level":"UNKNOWN"}}百度密钥申请方法:http://jingyan.baidu.com/article/363872eccda8286e4aa16f4e.html这样我就可以根据地址找到对应的经纬度了我爬的景点!辛辣的!Python获取经纬度json数据的代码如下:defgetBaiduGeo(sightlist,name):ak='key'headers={'User-Agent':'Mozilla/5.0(Macintosh;IntelMacOSX10_12_6)AppleWebKit/537.36(KHTML,likeGecko)Chrome/60.0.3112.113Safari/537.36'}address=addressurl='http://api.map.baidu.com/geocoder/v2/?address='+address+'&output=json&ak='+akjson_data=requests.get(url=url).json()json_geo=json_data['result']['location']观察得到的json文件,location中的数据与百度API要求的json格式基本一致,并且json文件中需要添加景区的销量。在这里可以了解json的浅拷贝和深拷贝知识,最后将排序后的json文件输出到本地文件。defgetBaiduGeo(sightlist,name):ak='密匙'headers={'User-Agent':'Mozilla/5.0(Macintosh;IntelMacOSX10_12_6)AppleWebKit/537.36(KHTML,likeGecko)Chrome/60.0.3112.113Safari/537.36'}list=sightlistbjsonlist=[]ejsonlist1=[]ejsonlist2=[]num=1forlinlist:try:try:try:address=l[6]url='http://api.map.baidu.com/geocoder/v2/?address='+address+'&output=json&ak='+akjson_data=requests.get(url=url).json()json_geo=json_data['result']['location']exceptKeyError,e:address=l[0]url='http://api.map.baidu.com/geocoder/v2/?address='+address+'&output=json&ak='+akjson_data=requests.get(url=url).json()json_geo=json_data['结果']['location']exceptKeyError,e:address=l[2]url='http://api.map.baidu.com/geocoder/v2/?address='+address+'&output=json&ak='+akjson_data=requests.get(url=url).json()json_geo=json_data['result']['location']exceptKeyError,e:continuejson_geo['count']=l[4]/100bjsonlist.append(json_geo)ejson1={l[0]:[json_geo['lng'],json_geo['lat']]}ejsonlist1=dict(ejsonlist1,**ejson1)ejson2={'name':l[0],'value':l[4]/100}ejsonlist2.append(ejson2)print'正在生成第一个'+str(num)+'景点经纬度'num+=1bjsonlist=json.dumps(bjsonlist)ejsonlist1=json.dumps(ejsonlist1,ensure_ascii=False)ejsonlist2=json.dumps(ejsonlist2,ensure_ascii=False)withopen('./points.json',"w")asf:f.write(bjsonlist)withopen('./geoCoordMap.json',"w")asf:f.write(ejsonlist1)withopen('./data.json',"w")asf:f.write(ejsonlist2)设置地址获取经纬度时,为了匹配更准确的经纬度,我选择了匹配景区地址。不过景区地址里面有各种神奇的地址。括号里的解释和XX相反,说Thereareabunchofthingsyoushouldturnleftandrighttogetthere,还有英文的。。。于是就有了第三章复杂的移除信息(终于找回来了!)但是,即使去掉了繁杂的信息,还是有一些景点地址无法匹配到,所以我使用了嵌套try。如无法匹配景区地址;然后匹配景点名称。如无法匹配景区名称;然后匹配景区所在区域。我……那我就……那我就跳过ㄒ_ㄒ……作为一个景点,你怎么会,好难找!不想你!这里生成的三个json文件,一个是百度地图API,另外两个是导入echarts的。网页读取json文件。将第2章介绍的百度地图API示例中的源码复制到解释器中,添加key,另存为html文件,打开即可看到和官网一样的显示效果。echarts需要在example页面,点击页面右上角的EN切换到英文版,然后点击downloaddemo下载完整源码。根据html导入json文件修改网页源码,导入json文件。#各位置修改部分百度地图api示例代码这里使用jQuery后,即使网页调试成功后,本地打开网页也无法显示。在chrome中右键,发现需要在服务器上显示错误信息,但是服务器是什么?百度一下,可以在本地创建一个服务器,在终端进入html文件所在的文件夹,输入python-mSimpleHTTPServer,然后在浏览器中打开http://127.0.0.1:8000/,记得要设置把html文件名改成index.html!只能拉取6K的经纬度API(懒惰的好理由),所以我选择了前400页(每页15个)的热门景点。结果可想而知,(?﹏?)为了调试因数据增加而产生的额外bug,最终得到的景点数据约4500条(爬取时间为2017年9月10日,爬取关键词:热门景点,只代表当时的销量)。热门景点热力图热门景点示意图这些是地图上最受欢迎的区域。我觉得国庆和这一次是这样的。提取地图上热门景点销量前20名。大多都是熟悉的地方,比如帝都的那些地方。故宫排名第一,大四川占据了前5名中的3个名额,在四川省20名名胜中占据了6个名额。如果不是因为地震,我想会有更多的热门景点进入排行榜~所以如果你这个国庆打算去四川,你能想象到的场景就是:大家大家大家大家大家大家大家、人、人、人、人……我还做了一个每个城市热门景点数量的排名。没想到在4000多个热门景点中,数量最多的还是我的大浙江,是第二城市的1.5倍。北京作为首都,也是……好吧,据说景点数量/总面积第一。各大城市热门景点数量这些城市的热门景点那么多,都是什么级别的景点?从下图可以看出,各个城市各个等级的景点数量与该城市的热门景点总量基本呈正相关,且主要由4A级景区贡献而来。各大城市热门景点等级知道了哪里人多,景点最多,那我们就来看看哪些地方最烧钱。下图是各城市景点起步价最高-最低扇形组成的圆圈,其中湖北位居首位,单个景点起步价600元。但也可以看出,湖北景区的平均销售价格并不高(红色区域中的深蓝色线)。还有如果你国庆去香港,请做好心理和身体准备,带上钱包减肥(??ω??)?。各省旅游景点销售起步价已经准备就绪。分析结束。ヾ(*ΦωΦ)ツ大家玩得开心。PS:我写了一个网页,在echarts中展示百度地图的热力图效果和景点排行榜,方便大家查看。热效应:http://easyinfo.onlinegayhub源码:https://github.com/otakurice/notravellist/tree/master写完这篇文章,发现echarts有一个针对Python的模块可以引入,于是打算学习一下Django、Flask等Web框架最近会有一些纯理论的意识流文章,一起进步吧~参考资料:1.地图API:http://developer.baidu.com/map/reference/index.php2.echarts:http://echarts.baidu.com/3.API使用示例:http://developer.baidu.com/map/jsdemo.htm#c1_154.json:http://www.runoob.com/json/json-tutorial.html5.xpath:http://www.runoob.com/json/json-tutorial.html5.xpath:runoob.com/xpath/xpath-tutorial.html6.pandas:http://python.jobbole.com/84416/7。百度经纬度api:http://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding8。浅拷贝和深拷贝:http://python.jobbole.com/82294/9.html导入json文件:http://www.jb51.net/article/36678.htm最后纪念一下苏享茂,WePhone的创始人,带着敬畏和遗憾。自杀前我不认识他,也不想以这种方式认识他。希望节目《共产党的世界》永远纯真无作弊。