炎炎夏日,朋友圈刷屏了大家的旅行足迹。那些基本上走遍了全国所有省份的朋友们,真的让我惊叹不已。同时也萌生了写旅游相关的内容。这次的数据来自一个对爬虫非常友好的旅游攻略网站:马蜂窝。1.获取城市编号马蜂窝所有的城市、景点等信息都有一个专属的5位编号。我们首先要做的是获取城市(直辖市+地级市)的编号,进行Follow-up做进一步分析。以上两页是我们城市代码的来源。您需要先从目的地页面获取各省代码,然后进入各省城市列表获取代码。过程中需要Selenium执行动态数据获取,部分代码如下:deffind_cat_url(url):headers={'User-Agent':'Mozilla/5.0(WindowsNT6.1;WOW64;rv:23.0)Gecko/20100101Firefox/23.0'}req=request.Request(url,headers=headers)html=urlopen(req)bsObj=BeautifulSoup(html.read(),"html.parser")bs=bsObj.find('div',attrs={'class':'hot-listclearfix'}).find_all('dt')cat_url=[]cat_name=[]foriinrange(0,len(bs)):forjinrange(0,len(bs[i].find_all('a'))):cat_url.append(bs[i].find_all('a')[j].attrs['href'])cat_name.append(bs[i].find_all('a')[j].text)cat_url=['http://www.mafengwo.cn'+cat_url[i]foriinrange(0,len(cat_url))]returncat_urldeffind_city_url(url_list):city_name_list=[]city_url_list=[]foriinrange(0,len(url_list)):driver=webdriver.Chrome()driver.maximize_window()url=url_list[i].replace('travel-scenic-spot/mafengwo','mdd/citylist')driver.get(url)whileTrue:try:time.sleep(2)bs=BeautifulSoup(driver.page_source,'html.parser')url_set=bs.find_all('a',attrs={'data-type':'目的地'})city_name_list=city_name_list+[url_set[i].text.replace('\n','').split()[0]foriinrange(0,len(url_set))]city_url_list=city_url_list+[url_set[i].attrs['data-id']foriinrange(0,len(url_set))]js="varq=document.documentElement.scrollTop=800"driver.execute_script(js)time.sleep(2)driver.find_element_by_class_name('pg-next').click()except:breakdriver.close()returncity_name_list,city_url_listurl='http://www.mafengwo.cn/mdd/'url_list=find_cat_url(url)city_name_list,city_url_list=find_city_url(url_list)city=pd.DataFrame({'city':city_name_list,'id':city_url_list})2.获取城市信息城市数据从以下页面获取:(a)小吃页面(b)景点页面(c)标签页面我们将获取每个城市的数据封装成一个函数,每次传入之前获取的城市代码,部分代码如下:]=city_namethis_city_jd['total_city_yj']=this_city_base['total_city_yj']尝试:this_city_food=get_city_food(city_name,city_code)this_city_food['city_name']=city_namethis_city_food['total_city_yj']=this_city_base['total_city_yj']except:this_city_food=pd.DataFrame()returnthis_city_base,this_city_food,this_city_jddefget_city_base(city_name,city_code):url='http://www.mafengwo.cn/xc/'+str(city_code)+'/'bsObj=get_static_url_content(url)node=bsObj.find('div',{'class':'m-tags'}).find('div',{'class':'bd'}).find_all('a')tag=[node[i].text.split()[0]foriinrange(0,len(node))]tag_node=bsObj.find('div',{'class':'m-tags'}).find('div',{'class':'bd'}).find_all('em')tag_count=[int(k.text)forkintag_node]par=[k.attrs['href'][1:3]forkinnode]tag_all_count=sum([int(tag_count[i])foriinrange(0,len(tag_count))])tag_jd_count=sum([int(tag_count[i])foriinrange(0,len(tag_count))ifpar[i]=='jd'])tag_cy_count=sum([int(tag_count[i])foriinrange(0,len(tag_count))ifpar[i]=='cy'])tag_gw_yl_count=sum([int(tag_count[i])foriinrange(0,len(tag_count))ifpar[i]in['gw','yl']])url='http://www.mafengwo.cn/yj/'+str(city_code)+'/2-0-1.html'bsObj=get_static_url_content(url)total_city_yj=int(bsObj.find('span',{'class':'count'}).find_all('span')[1].text)return{'city_name':city_name,'tag_all_count':tag_all_count,'tag_jd_count':tag_jd_count,'tag_cy_count':tag_cy_count,'tag_gw_yl_count':tag_gw_yl_count,'total_city_yj':total_city_yj}defget_city_food(city_name,city_code):url='http://www.mafengwo.cn/cy/'+str(city_code)+'/gonglve.html'bsObj=get_static_url_content(url)food=[k.textforkinbsObj.find('ol',{'class':'list-rank'}).find_all('h3')]food_count=[int(k.text)forkinbsObj.find('ol',{'class':'list-rank'}).find_all('span',{'class':'trend'})]returnpd.DataFrame({'food':food[0:len(food_count)],'food_count':food_count})defget_city_jd(city_name,city_code):url='http://www.mafengwo.cn/jd/'+str(city_code)+'/goglve.html'bsObj=get_static_url_content(url)node=bsObj.find('div',{'class':'row-top5'}).find_all('h3')jd=[k.text.split('\n')[2]forkinnode]node=bsObj.find_all('span',{'class':'rev-total'})jd_count=[int(k.text.replace('条点评价',''))forkinnode]returnpd.DataFrame({'jd':jd[0:len(jd_count)],'jd_count':jd_count})三、数据分析PART1:城市数据首先我们来看最大的那个numberofentrys***0cities:游记数量***0数量与我们每天知道的热门城市基本一致。我们进一步根据每个城市的游记数量得到一张全国旅游目的地热图:看到这个,是不是有一种似曾相识的感觉?如果你在朋友圈发的足迹图和这张图相符,就说明马蜂窝的数据和你的重合了***我们通过提取标签属性中的信息来看看大家对每个城市的印象,我们把属性分为三类组别:休闲、美食、景区。来看看每组属性下印象最深的城市:看来对于马蜂窝的用户来说,厦门给大家留下了非常深刻的印象,不仅游记数量充足,而且可以从中提取出很多有效的标签。重庆、西安、成都也毫无悬念地给吃货们留下了非常深刻的印象。部分代码如下:bar1=Bar("餐饮标签排名")bar1.add("餐饮标签评分",city_aggregate.sort_values('cy_point',0,False)['city_name'][0:15],city_aggregate.sort_values('cy_point',0,False)['cy_point'][0:15],is_splitline_show=False,xaxis_rotate=30)bar2=Bar("景点类别标签排名",title_top="30%")bar2.add("景点类别标签得分",city_aggregate.sort_values('jd_point',0,False)['city_name'][0:15],city_aggregate.sort_values('jd_point',0,False)['jd_point'][0:15],legend_top="30%",is_splitline_show=False,xaxis_rotate=30)bar3=Bar("休闲标签排名",title_top="67.5%")bar3.add("休闲标签得分",city_aggregate.sort_values('xx_point',0,False)['city_name'][0:15],city_aggregate.sort_values('xx_point',0,False)['xx_point'][0:15],legend_top="67.5%",is_splitline_show=False,xaxis_rotate=30)grid=Grid(height=800)grid.add(bar1,grid_bottom="75%")grid.add(bar2,grid_bottom="37.5%",grid_top="37.5%")grid.add(bar3,grid_top="75%")grid.render('cityclassificationlabel.html')PART2:观光数据我们提取了每个景点的点评数量,并与城市的数量进行对比游记获取景点点评的绝对值和相对值是根据景点的知名度和代表性得分来计算的。5大景点最终排名如下:马蜂窝网友对厦门真是情有独钟,鼓浪屿也成为了热门景点,西塘古镇和羊卓雍措城市名列前茅代表性旅游胜地。PART3:零食数据***来看看大家最关心的与食物相关的数据。处理方式与PART2景区数据类似。一起来看看***市最受欢迎和最具代表性的小吃吧。没想到,马蜂窝网友对厦门情有独钟,让沙茶面超越火锅、烤鸭、夹肉,成为最受欢迎的小吃。在城市表征方面,海鲜的出现频率非常高,这与大(本)族(ren)的认知不谋而合。PART2、3部分代码如下:bar1=Bar("景点人气排名")bar1.add("景点人气得分",city_jd_com.sort_values('rq_point',0,False)['jd'][0:15],city_jd_com.sort_values('rq_point',0,False)['rq_point'][0:15],is_splitline_show=False,xaxis_rotate=30)bar2=Bar("景点代表排名",title_top="55%")bar2.add("景点代表分数",city_jd_com.sort_values('db_point',0,False)['jd'][0:15],city_jd_com.sort_values('db_point',0,False)['db_point'][0:15],is_splitline_show=False,xaxis_rotate=30,legend_top="55%")grid=Grid(height=800)grid.add(bar1,grid_bottom="60%")网格。add(bar2,grid_top="60%",grid_bottom="10%")grid.render('景点排名.html')本文涉及的所有代码已发至Github,欢迎大家提取:http://github.com/shujusenlin/mafengwo_data。作者:徐琳,知乎同名专栏作家,目前就职于上海唯品会产品技术中心,哥伦比亚大学统计数据狗,从事数据挖掘&分析,喜欢用R&Python玩转一些不同的数据。
