引用

那么问题来了,去哪儿玩呢?百度输了个“国庆”,出来的第一条居然是“去哪里旅游人少”……emmmmmmm,因缺思厅。

于是我萌生了通过旅游网站的景点销量来判断近期各景点流量情况的想法(这个想法很危险啊)。

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

1.百度的地图API和echarts

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

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

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

再详细一点讲呢,就好比米酱的小说写完啦!但她还想把小说出成书,可是怎么出书捏?米酱不会呀,这时候米酱发现某出版社提供了出版服务,出版社表示只需要提供小说的正文、以及一个设计的封面就可以啦,于是米酱将小说保存成了word格式,又画了个封面jpg图,发给了出版社,没过多久米酱就拿到了一本装订好的书啦(此段纯属虚构,专业出版人士尽管打我,我不会承认的)。

在米酱出书的过程中,米酱并不需要知道出版社是怎么印刷这个书的,也不需要知道是怎么装订这个书的,米酱只需要提供出版社所要求的东西即可。

2.确定输出文件

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

但是!

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

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

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

echarts也是一样滴(*\^__^*)。

3.爬取数据

实这次的爬虫部分是比较简单的(如果你有跟着我的文爬过网站的话)。

分析网址(去哪儿景点)→爬取分页中信息(景点经纬度、销量)→转为json文件。

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

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

def getList():

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

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

i = 1

sightlist = []

while i:

page = getPage(url.format(i))

selector = etree.HTML(page)

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

i+=1

informations = selector.xpath('//div[@class="result_list"]/div')

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

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

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

if len(sight_level):

sight_level = sight_level[0].replace('景区','')

else:

sight_level = 0

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

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

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

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

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

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

if len(sight_price):

sight_price = sight_price[0]

else:

i = 0

break

sight_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('地址:',''),sight_slogen,sight_url])

time.sleep(3)

return sightlist,place

这里把每个景点的所有信息都爬下来了(其实是为了练习使用xpath……)。

使用了while循环,for循环的break的方式是发现无销量时给i值赋零,这样while循环也会同时结束。

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

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

def listToExcel(list,name):

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

df.to_excel(name + '景点信息.xlsx')

5.百度经纬度api

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

但是,enhahhahahaha,我怎么会放弃呢,我又找到了百度经纬度api,网址:http://api.map.baidu.com/geocoder/v2/?address=地址&output=json&ak=百度密钥,修改网址里的“地址”和“百度密钥”,在浏览器打开,就可以看到经纬度的json信息。

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

{"status":0,"result":{"location":{"lng":121.5064701060957,"lat":31.245341811634675},"precise":1,"confidence":70,"level":"UNKNOWN"}

百度密钥申请方法

这样我就可以根据爬到的景点地址,查到对应的经纬度辣!python获取经纬度json数据的代码如下。

def getBaiduGeo(sightlist,name):

ak = '密钥'

headers = {

'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'

}

address = 地址

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

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

json_geo = json_data['result']['location']

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

def getBaiduGeo(sightlist,name):

ak = '密钥'

headers = {

'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'

}

list = sightlist

bjsonlist = []

ejsonlist1 = []

ejsonlist2 = []

num = 1

for l in list:

try:

try:

try:

address = l[6]

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

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

json_geo = json_data['result']['location']

except KeyError,e:

address = l[0]

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

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

json_geo = json_data['result']['location']

except KeyError,e:

address = l[2]

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

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

json_geo = json_data['result']['location']

except KeyError,e:

continue

json_geo['count'] = l[4]/100

bjsonlist.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 +=1

bjsonlist =json.dumps(bjsonlist)

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

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

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

f.write(bjsonlist)

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

f.write(ejsonlist1)

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

f.write(ejsonlist2)

(╯’ - ‘)╯┻━┻

在设置获取经纬度的地址时,为了匹配到更准确的经纬度,我选择了匹配景点地址,然鹅,景点地址里有各种神奇的地址,带括号解释在XX对面的,说一堆你应该左拐右拐各种拐就能到的,还有英文的……于是就有了第三章中复杂的去除信息(我终于圆回来了!)。

然鹅,就算去掉了复杂信息,还有一些匹配不到的景点地址,于是我使用了嵌套try,如果景点地址匹配不到;就匹配景点名称,如果景点名称匹配不到;就匹配景点所在区域,如果依然匹配不到,那我……那我就……那我就跳过ㄒ_ㄒ……身为一个景点,你怎么能,这么难找呢!不要你了!

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

6.网页读取json文件

将第二章中所述的百度地图api示例中的源代码复制到解释器中,添加密钥,保存为html文件,打开就可以看到和官网上一样的显示效果。echarts需要在实例页面,点击页面右上角的EN切换到英文版,然后点击download demo下载完整源代码。

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

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

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

var points = data;

script中原有函数;

});

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

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

7.后记

因为注册但没有认证开发者账号,所以每天只能获取6K个经纬度api(这是一个很好的偷懒理由),所以我选择了热门景点中前400页(每页15个)的景点,结果可想而知,(ಥ﹏ಥ)为了调试因为数据增多出现的额外bug,最终的获取的景点数据大概在4k5条左右(爬取时间为2017年09月10日,爬取关键词:热门景点,仅代表当时销量)。

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

这样的

还有这样的

将地图上热门景点的销量top20提取出来,大多数都是耳熟能详的地点,帝都的故宫排在了第一位,而大四川则占据了top5中的三位,而排在top20中也四川省就占了6位,如果不是因为地震,我想还会有更多的火爆的景点进入排行榜的~这样看来如果你这次国庆打算去四川的话,可以脑补到的场景就是:人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人……

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

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

既然去哪些地方人多,去哪里景多都已经知道了,那再看看去哪些地方烧得钱最多吧?下图是由各城市景点销售起步价的最大值-最小值扇形组成的圆,其中湖北以单景点销售起步价600占据首位,但也可以看到,湖北的景点销售均价并不高(在红色扇形中的藏蓝色线条)。而如果国庆去香港玩,请做好钱包减肥的心理和生理准备(•̀ω•́)✧。

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

PS:写了个网页,展示百度地图的热力图效果和echarts的景点排行榜,方便大家查看。http://easyinfo.online 源码已经上传到gayhub啦\~写完这篇文的时候发现echarts有针对python的模块可以引入,所以打算去学一下Django、Flask之类的web框架,最近会更一些纯理论的意识流文,大家一起进步吧~

python爬虫去哪儿网_用python爬虫爬取去哪儿4500个热门景点,看看国庆不能去哪儿...相关推荐

  1. python爬虫携程酒店_携程酒店爬取分享

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 import urllib.request from bs4 import BeautifulSoup import csv import re def ...

  2. Python 网络爬虫实战:去哪儿网旅游攻略图文爬取保存为 Markdown电子书

    接上回,<Python 网络爬虫实战:爬取<去哪儿>网数千篇旅游攻略数据>. 我们爬取到了数千篇的旅游攻略文章的数据. 但是事情还没有结束,对于大部分的人来讲,最希望得到的东西 ...

  3. python 批量下载网页图片_手把手教你爬取天堂网1920*1080大图片(批量下载)——实战篇|python基础教程|python入门|python教程...

    https://www.xin3721.com/eschool/pythonxin3721/ /1 前言/ 上篇文章 手把手教你爬取天堂网1920*1080大图片(批量下载)--理论篇我们谈及了天堂网 ...

  4. python爬虫搜狐新闻_应用案例2:爬取搜狐体育的新闻信息

    爬虫学习使用指南 Auth: 王海飞 Data:2018-06-25 Email:779598160@qq.com github:https://github.com/coco369/knowledg ...

  5. python 实现链家网房源数据信息的爬取

    又到了一年一度的盛大毕业季了,千千万万的莘莘学子就要离开校园走向全国各地的工作岗位了,离开家乡,离开校园,租房就变成了一个重要的问题,那么如何才能够更好地找到符合自己的房子呢,这里就是想构建一个房源信 ...

  6. python词云代码手机_【云计算】爬取淘宝手机品牌词云分析(python)

    本文主要向大家介绍了[云计算]爬取淘宝手机品牌词云分析(python),通过具体的内容向大家展现,希望对大家学习云计算有所帮助. 淘宝手机信息的爬取,请看这边博客(点击这里),然后我们利用其中保存的文 ...

  7. 爬虫练手项目_酷狗音乐爬取

    酷狗音乐爬虫 前言 分析网站 第一步 第二步 第三步 第四步 准备爬虫 大体框架 获取signature 完整代码 前言 利用暑假闲暇时间学习了一下爬虫,也尝试了几个爬取图片的小项目,但感觉爬取图片有 ...

  8. python爬虫之云片网国内短信接口爬取

    安装requests,lxml,openpyxl,pandas四个包. requests爬取 lxml解析 panda转换并保存 openpyxl是读写excel文件所用到的包 代码奉上: impor ...

  9. python中国最好大学排名_三分钟实现爬取中国前20大学排名

    一.中国大学排名爬虫案例的步骤如下: 步骤1:从网络上获取大学排名网页内容 getHTMLText() 步骤2:提取网页内容中信息到合适的数据结构 fillUnivList() 步骤3:利用数据结构展 ...

最新文章

  1. Python 中读取和保存图像方法汇总及其区别
  2. Jsp内置对象及EL表达式的使用
  3. LED音乐频谱之输出数据处理
  4. 服务器系统选择什么,服务器选择什么系统
  5. C#语法基础之第三节
  6. 从0到70%:Chrome上位揭秘!
  7. 提高 服务器 内存 利用率_怎样提高AI服务器的利用率
  8. VC++ ToolTip的简单使用
  9. 深入浅析HTML5中的article和section的区别
  10. 初学ACM之路(训练大纲)
  11. 如何用Pygame写游戏(十七)
  12. JAVA学生信息管理系统IO流版
  13. 【C语言】fgets函数返回值
  14. ActiveMQ Destination高级特性
  15. tornado框架介绍
  16. ES10新特性_数组方法扩展flat_与flatMap---JavaScript_ECMAScript_ES6-ES11新特性工作笔记059
  17. jq使用教程05_ 新手也能用的安装版本,30秒点选即可安装完成,不需配置Python环境
  18. c++ windows 光标操作_电脑操作常用快捷键
  19. Flutter跨组件共享状态的利器Provider原理解析
  20. 2022-4-12作业

热门文章

  1. android显示伽玛曲线,android – 伽玛曲线实验 – 将2.2转换为1.8的相反值?
  2. kaggle gradient_descent
  3. OpenGL3.3transform feedback再理解
  4. loadrunner入门教程(10)--代理录制
  5. 企业闪存应用八年回顾
  6. C.H. Robinson罗宾逊全球物流在Gartner实时交通可视化平台魔力象限报告中被评为“挑战者”
  7. JS 实现网页的简体繁体切换
  8. 使用主密钥和钱包方法加密数据
  9. 2020 阿里最新面试题,掌握这些轻松拿offer
  10. 影响PCB电路板焊接质量的原因有哪些?