模板户:专注于dede模板,织梦源码,织梦模板,网站模板,dedecms模板,网站源码,dedecms教程以及各类手机网站模板和企业网站模板分享.

织梦模板

VIP

CMS教程

站长学院

随机织梦教程

最新织梦教程

织梦模板随机Tags

关键词排名 原创 用户体验 玩具外贸网站源码 关键词优化 搜索引擎 汽车配件织梦模板 网站title 太阳能光伏网站源码 网站 财务会计网站源码 餐饮管理织梦模板 餐饮加盟网站源码 关键词 汽车润滑油网站源码 蜘蛛 优化 织梦伪静态 高亮 个人网站

我用Python爬取了全国4500个热门景点,告诉你国庆节哪儿最堵?

www.mobanhu.com / 2017-12-24 00:10:00

金秋九月,丹桂飘香,在这秋高气爽,阳光灿烂的收获季节里,我们送走了一个个暑假余额耗尽哭着走向校园的孩子们,又即将迎来一年一度伟大祖国的生日(无心上班,迫不及待想为祖国庆生)。

那么问题来了,去哪儿玩呢?


百度输了个“国庆”,出来的第一条居然是“去哪里旅游人少”……因缺思厅。


于是,我萌生了通过旅游网站的景点销量来判断近期各景点流量情况的想法。


所以这次的目标,是爬去哪儿网景点页面,并得到景点的信息,大家可以先思考下大概需要几步。



百度的地图 API 和 echarts


因为前几次爬虫都是爬一些文本信息,做一下词云之类的,我觉得:没!意!思!了!


这次正好爬的是数据,我决定用数据的好基友——图表来输出我爬取的数据,也就是说我要用爬取的景点销量以及景点的具体位置来生成一些可视化数据。


安利一下百度的地图 API 和 echarts,前者是专门提供地图 API 的工具,听说好多 APP 都在用它,后者是数据处理居家旅行的好伙伴,用了之后,它好,我也好(隐约觉得哪里不对)。


API 是什么,API 是应用程序的编程接口,就好像插头与插座一样,我们的程序需要电(这是什么程序?),插座中提供了电,我们只需要在程序中写一个与插座匹配的插头接口,就可以使用电来做我们想做的事情,而不需要知道电是如何产生的。


引入数据后的百度热力图

通过 API 对接的开发者与服务商



确定输出文件


有人可能说,我已经懂了 API 是啥意思了,可是咋个用呢。关于这一点,我很负责任的告诉你:我也不会。


但是!百度地图提供了很多 API 使用示例,有 html 基础,大致可以看懂,有 js 基础就可以尝试改函数了(不会 js 的,我默默地复制源代码),仔细观察源代码,可以知道热力图生成的主要数据都存放在 points 这个变量中。



这种[{x:x,x:x},{x:x,x:x}]格式的数据,是一种 json 格式的数据,由于具有自我描述性,所以比较通俗易懂,大概可以知道这里的三个值,前两个是经纬度,最后一个应该是权重(我猜的)。


也就是说,如果我希望将景点的热门程度生成为热力图,我需要得到景点的经纬度,以及它的权重,景点的销量可以作为权重,并且这个数据应该是 json 格式的呈现方式。


echarts 也是一样的。



爬取数据


这次的爬虫部分是比较简单的。分析网址(去哪儿景点)→爬取分页中信息(景点经纬度、销量)→转为 json 文件。


分析去哪儿景点页的网址,可得出结构:http://piao.qunar.com/ticket/list.htm?keyword=搜索地点®ion=&from=mpl_search_suggest&page=页数


这次没有用正则来匹配内容,而使用了 xpath 匹配,非常好用。


  1. def getList(): 

  2.     place = raw_input(请输入想搜索的区域、类型(如北京、热门景点等):

  3.     url = http://piao.qunar.com/ticket/list.htm?keyword=+ str(place) +&region=&from=mpl_search_suggest&page={} 

  4.     i = 1 

  5.     sightlist = [] 

  6.     while i: 

  7.         page = getPage(url.format(i)) 

  8.         selector = etree.HTML(page) 

  9.         print 正在爬取第 + str(i) + 页景点信息 

  10.         i+=1 

  11.         informations = selector.xpath(//[@class="result_list"]/

  12.         for inf in informations: #获取必要信息 

  13.             sight_name = inf.xpath(.///h3/a/text())[0] 

  14.             sight_level = inf.xpath(.//span[@class="level"]/text()

  15.             if len(sight_level): 

  16.                 sight_level = sight_level[0].replace(景区,

  17.             else

  18.                 sight_level = 0 

  19.             sight_area = inf.xpath(.//span[@class="area"]/a/text())[0] 

  20.             sight_hot = inf.xpath(.//span[@class="product_star_level"]//span/text())[0].replace(热度 ,

  21.             sight_add = inf.xpath(.//p[@class="address color999"]/span/text())[0] 

  22.             sight_add = re.sub(地址:|(.*?)|(.*?)|,.*?$|/.*?$,,str(sight_add)) 

  23.             sight_slogen = inf.xpath(.//[@class="intro color999"]/text())[0] 

  24.             sight_price = inf.xpath(.//span[@class="sight_item_price"]/em/text()

  25.             if len(sight_price): 

  26.                 sight_price = sight_price[0] 

  27.             else

  28.                 i = 0 

  29.                 break 

  30.             sight_soldnum = inf.xpath(.//span[@class="hot_num"]/text())[0] 

  31.             sight_url = inf.xpath(.//h3/a[@class="name"]/@href)[0] 

  32.             sightlist.append([sight_name,sight_level,sight_area,float(sight_price),int(sight_soldnum),float(sight_hot),sight_add.replace(地址:,),sight_slogen,sight_url]) 

  33.         time.sleep(3) 

  34.     return sightlist,place 

这里把每个景点的所有信息都爬下来了。使用了 while 循环,for 循环的 break 的方式是发现无销量时给 i 值赋零,这样 while 循环也会同时结束。


地址的匹配使用 re.sub() 函数去除了 n 多复杂信息,这点后面解释。

  •  


输出本地文本

  •  

为了防止代码运行错误,维护代码运行的和平,将输出的信息列表存入到 excel 文件中了,方便日后查阅,很简单的代码,需要了解 pandas 的用法。

  1. def listToExcel(list,name): 

  2.     df = pd.DataFrame(list,columns=[景点名称,级别,所在区域,起步价,销售量,热度,地址,标语,详情网址]) 

  3.     df.to_excel(name + 景点信息.xlsx



百度经纬度 API


非常悲伤的,(ಥ﹏ಥ)我没找到去哪儿景点的经纬度,以为这次学习计划要就此流产了。(如果有人知道景点经纬度在哪里请告诉我)


但是,我怎么会放弃呢,我又找到了百度经纬度 API。


网址:http://api.map.baidu.com/geocoder/v2/?address=地址&output=json&ak=百度密钥,修改网址里的“地址”和“百度密钥”,在浏览器打开,就可以看到经纬度的 json 信息。


  1. #上海市东方明珠的经纬度信息 

  2. {"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 数据的代码如下:


  1. def getBaiduGeo(sightlist,name): 

  2.     ak = 密钥 

  3.     headers = { 

  4.     User-Agent :Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36 

  5.     } 

  6.     address = 地址 

  7.     url = http://api.map.baidu.com/geocoder/v2/?address= + address  + &output=json&ak= + ak 

  8.     json_data = requests.get(url = url).json() 

  9.     json_geo = json_data[result][location

观察获取的 json 文件,location 中的数据和百度 API 所需要的 json 格式基本是一样,还需要将景点销量加入到 json 文件中,这里可以了解一下 json 的浅拷贝和深拷贝知识,最后将整理好的 json 文件输出到本地文件中。


  1. def getBaiduGeo(sightlist,name): 

  2.     ak = 密钥 

  3.     headers = { 

  4.     User-Agent :Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36 

  5.     } 

  6.     list = sightlist 

  7.     bjsonlist = [] 

  8.     ejsonlist1 = [] 

  9.     ejsonlist2 = [] 

  10.     num = 1 

  11.     for l in list: 

  12.         try: 

  13.             try: 

  14.                 try: 

  15.                     address = l[6] 

  16.                     url = http://api.map.baidu.com/geocoder/v2/?address= + address  + &output=json&ak= + ak 

  17.                     json_data = requests.get(url = url).json() 

  18.                     json_geo = json_data[result][location

  19.                 except KeyError,e: 

  20.                     address = l[0] 

  21.                     url = http://api.map.baidu.com/geocoder/v2/?address= + address  + &output=json&ak= + ak 

  22.                     json_data = requests.get(url = url).json() 

  23.                     json_geo = json_data[result][location

  24.             except KeyError,e: 

  25.                     address = l[2] 

  26.                     url = http://api.map.baidu.com/geocoder/v2/?address= + address  + &output=json&ak= + ak 

  27.                     json_data = requests.get(url = url).json() 

  28.                     json_geo = json_data[result][location

  29.         except KeyError,e: 

  30.             continue 

  31.         json_geo[count] = l[4]/100 

  32.         bjsonlist.append(json_geo) 

  33.         ejson1 = {l[0] : [json_geo[lng],json_geo[lat]]} 

  34.         ejsonlist1 = dict(ejsonlist1,**ejson1) 

  35.         ejson2 = {name : l[0],value : l[4]/100} 

  36.         ejsonlist2.append(ejson2) 

  37.         print 正在生成第 + str(num) + 个景点的经纬度 

  38.         num +=1 

  39.     bjsonlist =json.dumps(bjsonlist) 

  40.     ejsonlist1 = json.dumps(ejsonlist1,ensure_ascii=False

  41.     ejsonlist2 = json.dumps(ejsonlist2,ensure_ascii=False

  42.     with open(./points.json,"w"as f: 

  43.         f.write(bjsonlist) 

  44.     with open(./geoCoordMap.json,"w"as f: 

  45.         f.write(ejsonlist1) 

  46.     with open(./data.json,"w"as f: 

  47.         f.write(ejsonlist2) 

在设置获取经纬度的地址时,为了匹配到更准确的经纬度,我选择了匹配景点地址,然而,景点地址里有各种神奇的地址,带括号解释在 XX 对面的,说一堆你应该左拐右拐各种拐就能到的,还有英文的……


于是就有了第三章中复杂的去除信息(我终于圆回来了!)。


然而,就算去掉了复杂信息,还有一些匹配不到的景点地址,于是我使用了嵌套 try,如果景点地址匹配不到;就匹配景点名称,如果景点名称匹配不到;就匹配景点所在区域,如果依然匹配不到,那我……那我就……那我就跳过ㄒ_ㄒ……


身为一个景点,你怎么能,这么难找呢!不要你了!


这里生成的三个 json 文件,一个是给百度地图 API 引入用的,另两个是给 echarts 引入用的。



网页读取 json 文件


将第二章中所述的百度地图 API 示例中的源代码复制到解释器中,添加密钥,保存为 html 文件,打开就可以看到和官网上一样的显示效果。


echarts 需要在实例页面,点击页面右上角的 EN 切换到英文版,然后点击 download demo 下载完整源代码。


根据 html 导入 json 文件修改网页源码,导入 json 文件。


  1. #百度地图api示例代码中各位置修改部分 

  2. <head> 

  3.     <script src="http://libs.baidu.com/jquery/2.0.0/jquery.js"></script> 

  4. </head> 

  5. <script type="text/javascript"

  6.     $.getJSON("points.json"function(data){ 

  7.         var points = data; 

  8.         script中原有函数; 

  9.         }); 

  10. </script> 


这里使用了 jQuery 之后,即使网页调试成功了,在本地打开也无法显示网页了,在 chrome 中右键检查,发现报错提示是需要在服务器上显示,可是,服务器是什么呢?


百度了一下,可以在本地创建一个服务器,在终端进入到 html 文件所在文件夹,输入 python -m SimpleHTTPServer,再在浏览器中打开 http://127.0.0.1:8000/,记得要将 html 文件名设置成 index.html 哦!




后记


因为注册但没有认证开发者账号,所以每天只能获取 6K 个经纬度 API(这是一个很好的偷懒理由),所以我选择了热门景点中前 400 页(每页 15 个)的景点。


结果可想而知,(ಥ﹏ಥ)为了调试因为数据增多出现的额外 Bug,最终的获取的景点数据大概在 4500 条左右(爬取时间为 2017 年 9 月 10 日,爬取关键词:热门景点,仅代表当时销量)。


热门景点热力图

热门景点示意图

这些地图上很火爆的区域,我想在国庆大概是这样的

这样的

还有这样的

将地图上热门景点的销量 Top20 提取出来,大多数都是耳熟能详的地点,北京的故宫排在了第一位,而四川则占据了 Top5 中的三位,排在 Top20 中四川省景点就占了 6 位。


如果不是因为地震,我想还会有更多的火爆的景点进入排行榜的~这样看来如果你这次国庆打算去四川的话,可以脑补到的场景就是:人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人……


热门景点销量Top20

于是我又做了一个各城市包含热门景点数目的排行,没想到在 4 千多个热门景点中,数目最多的竟是我大浙江,是第二个城市的 1.5 倍,而北京作为首都也……可以说是景点数/总面积的第一位了。


主要城市热门景点数

这些城市有辣么多热门景点,都是些什么级别的景点呢?由下图看来,各城市的各级别景点基本与城市总热门景点呈正相关,而且主要由 4A 景区贡献而来。


主要城市热门景点级别


既然去哪些地方人多,去哪里景多都已经知道了,那再看看去哪些地方烧得钱最多吧。


下图是由各城市景点销售起步价的最大值-最小值扇形组成的圆,其中湖北以单景点销售起步价 600 占据首位。


但也可以看到,湖北的景点销售均价并不高(在红色扇形中的藏蓝色线条)。而如果国庆去香港玩,请做好钱包减肥的心理和生理准备(•̀ω•́)✧。


各省旅游景点销售起步价


好啦分析完啦,ヾ(*ΦωΦ)ツ大家可要好好玩呀。

 

来源:51CTO

-end-

往期回顾:

iPhone8 下周出击,吓得我捂紧了我的肾!

以后,在微信里管好自己的嘴,千万别妄议!

做CIO难!做不踩“坑”的CIO更难!

Gartner发布技术成熟曲线:“你刚被人工智能洗脑,最聪明的钱已转向这16项技术”

记一次惊心动魄的 DNS 缓存引发的惨案 

发现·前沿 《海外风向标》|  对话·精英 《CXO百脑汇》|  聚焦·行业 《早安,IDG》|   每周精彩内容,尽在e行网。 

投诉
本文由AB模板网:织梦模板整理发布, 转载请说明出处:https://www.mobanhu.com
随机站长资讯
高级精美的家私企业网站源码 家私家纺类网
农业绿色生态水果企业dede源码
驾校类企业网站源码 驾校网站模板
绿色LED灯管类织梦源码 照明企业网站模板
蓝色通用织梦博客模板 资讯文章类网站源码
红色大气装饰公司织梦源码 建筑装修装潢企
网站建设企业模板 互联网网络营销类网站源
html5响应式手机自适应网站模板(兼容手机
黑色HTML5工作室网络公司网站整站模板(适
简洁大气网站建设网络设计类企业织梦模板
html5+css3高端网站建设工作室源码 酷炫的h
红灰色大气网络工作室织梦模板
织梦dedecms幻灯片模糊解决办法
织梦dedecms巧用标签实现图片自动Alt功能,
织梦dedecms文章列表循环标签增加notypeid
织梦dedecms专题模板应用分析及使用案例
dedecms织梦让二级栏目标题去除“/”斜杠和
最新站长资讯
高级精美的家私企业网站源码 家私家纺类网
农业绿色生态水果企业dede源码
驾校类企业网站源码 驾校网站模板
绿色LED灯管类织梦源码 照明企业网站模板
蓝色通用织梦博客模板 资讯文章类网站源码
红色大气装饰公司织梦源码 建筑装修装潢企
网站建设企业模板 互联网网络营销类网站源
html5响应式手机自适应网站模板(兼容手机
黑色HTML5工作室网络公司网站整站模板(适
简洁大气网站建设网络设计类企业织梦模板
html5+css3高端网站建设工作室源码 酷炫的h
红灰色大气网络工作室织梦模板
织梦dedecms幻灯片模糊解决办法
织梦dedecms巧用标签实现图片自动Alt功能,
织梦dedecms文章列表循环标签增加notypeid
织梦dedecms专题模板应用分析及使用案例
dedecms织梦让二级栏目标题去除“/”斜杠和
关于出现“对不起,您安装的不是正版应用..
Discuz(Can not write to cache files)有关
Discuz通过修改文章标题更好的实现SEO的方
DiscuzX中存在不合法的文件被上传的修复方
关于Discuz x3.1页面空白解决方法
首页 免费源码 VIP专区 会员中心
收缩