**作者:**Mr. Ceong
链接:http://blog.csdn.net/leigaiceong/article/details/53188454

Python3 实现大众点评网酒店信息和酒店评论的网页爬取


概要

本文根据已有的的”大众点评网”酒店主页的URL地址,自动抓取所需要的酒店的名称、图片、经纬度、酒店价格、星级评分、用户评论数量以及用户评论的用户ID、用户名字、评分、评论时间等,并且将爬取成功的内容存放到.txt文档中。本文是在博文http://blog.csdn.net/drdairen/article/details/51146961的基础上进行实现和完善。因此十分感谢该文作者的无私奉献!


正文

一、基本信息

  • 编程语言: Python 3.5.2
  • 实现平台: Eclipse for Pydev
  • 实现功能:
    1.爬取酒店的基本信息(包括:酒店名称、地址、图片、经纬度、酒店价格、星级评分、用户评论数量)
    2.爬取酒店的评论信息(包括:酒店评论用户ID、用户名字、房间评分、服务评分、总评分、评价时间、酒店评论内容
  • 实现代码: http://download.csdn.net/detail/qq_22107075/9668373
  • 注意事项:
    1.在抓取大众点评网的评论的时候如果访问大众点评网的频率过于频繁会导致大众点评网的反爬虫技术短暂屏蔽PC的IP地址(时长不定)
    2.本文通过设置Python的time模块的sleep time来限定爬取评论的时间

二、实现过程

本文爬取的内容为广州市天河区附近用户评论数大于100的热门酒店(按评论数排名,如下图)。

实现思路

程序解读

  1. 程序总共包含5个模块

    DianpingSpider.py 主程序
    picture.py 爬取酒店图片
    position.py 根据POI参数转换成经纬度
    PriceAndScores.py 爬取酒店价格和星级评分
    urlspider.py 爬取广州市天河区附近热门酒店的URL
    文件夹 hotel 存放成功爬取的酒店信息和用户评论
    文件夹 image 存放成功爬取的酒店图片
  2. 模块解说
    (1)DianpingSpider.py
    该模块是实现本文的主程序,只要运行本程序即可实验本文功能。主要功能是调用另外四个模块及实现其他未实现的功能(详情请看代码)

实现原理为爬虫常用的Python 3模块,如:urllib.request、re、time,网上学习资料非常多,在此不作赘诉,烦请自己google。

import urllib.request
import re
import time
import picture #获取酒店图片
import urlspider #获取酒店的主页网址
import position #获取酒店的经纬度
import os
import random
import PriceAndScores #获取酒店的价格和星级评分# 统计所有酒店的评价信息,存入文本
def getRatingAll(fileIn):count =0          # 计数,显示进度websitenumber=0for line in open(fileIn,'r'):     # 逐行读取并处理文件,即hotel的urlcount=line.split('\t')[0]line=line.split('\t')[1] websitenumber+=1print("正在抓取第%s个网址的酒店信息"%(websitenumber))try:print("正在抓取第%s家酒店的信息,网址为%s"%(count,line.strip('\n')))# 获取酒店编号hotelid = line.strip('\n').split('/')[4]#print('该酒店的hotelid是 : ', hotelid)# 拼凑出该酒店第一页"评论页面"的urlurl = line.strip('\n') + "/review_more"#print('该酒店第一页"评论页面"的url是', url)# 模拟浏览器,打开urlheaders = ('User-Agent', 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko')opener = urllib.request.build_opener()opener.addheaders = [headers]data = opener.open(url).read()#print(data)  当访问大众点评网过于次数频繁的时候,大众点评网的反爬虫技术会封锁本机的IP地址,此时data就会出现异常,无法打印正常的htmldata = data.decode('utf-8', 'ignore')#print(data)# 获取酒店用户评论数目rate_number = re.compile(r'全部点评</a><em class="col-exp">\((.*?)\)</em></span>', re.DOTALL).findall(data)rate_number = int(''.join(rate_number))  # 把列表转换为str,把可迭代列表里面的内容用‘ ’连接起来成为str,再进行类型转换print("第%d家酒店的评论数为%s" % (websitenumber, rate_number))if(rate_number<100):#若酒店评论数目少于100条,则不跳过该酒店,不再挖取信息continue# 获取酒店名称和地址opener1 = urllib.request.build_opener()opener1.addheaders = [headers]hotel_url =opener1.open(line).read()hotel_data = hotel_url.decode('utf-8')#ignore是忽略其中有异常的编码,仅显示有效的编码#print(hotel_data)  #当访问大众点评网过于次数频繁的时候,大众点评网的反爬虫技术会封锁本机的IP地址,此时hotel_data就会出现异常,无法打印正常的html# 获取酒店名称shop_name=re.compile(u'<h1 class="shop-name">(.*?)    </h1>',re.DOTALL).findall(hotel_data)shop_name=str(''.join(shop_name)) #类型转换shop_name=shop_name.strip() #去掉字符串中的换行符# 获取酒店地址address=re.compile(u'<p class="shop-address">地址:&nbsp;(.*?)\n         <span>',re.DOTALL).findall(hotel_data)address=str(''.join(address))#print(address)# 获取酒店经纬度poi=re.compile(r'poi: \"(.*?)\",',re.DOTALL).findall(hotel_data)poi=str(''.join(poi))(longitude,latitude)=position.getPosition(poi)print("longitude:%s°E,latitude:%s°N"%(longitude,latitude))#获取酒店评分和酒店价格(price,scores)=PriceAndScores.getPriceAndScores(line.strip('\n'))# 获取酒店图片PictureOut ='.\\image\\'+str(count)+" "+shop_namepicture.getPicture(line.strip('\n'), PictureOut)#保存酒店信息fileOut='.\\hotel\\'+str(count)+" "+shop_name+'.txt'if os.path.exists(fileOut):os.remove(fileOut)fileOp = open(fileOut, 'a', encoding="utf-8")fileOp.write("酒店名称: %s\n酒店网址: %s\n地址: %s\n经度: %s°E,纬度: %s°N\n酒店评分: %d stars\n酒店价格:¥ %d 元起/人\n评论数量: %s\n"%(shop_name,line.strip('\n'),address,longitude,latitude,scores,price,rate_number))fileOp.write( "酒店ID \t\t 用户ID \t\t 用户名字 \t\t 房间评分  \t\t 服务评分 \t\t 用户总评分 \t\t 评价时间 \n")fileOp.close()FileName='.\\hotel\\'+str(count)+" "+shop_name+' 用户评论.txt'if os.path.exists(FileName):os.remove(FileName)# 解析评分pages = int(rate_number / 20) + 1  # 由评论数计算页面数,大众点评网每页最多20条评论.# print(pages)for i in range(1, pages + 1):# 打开页面add_url = url + '?pageno=' + str(i)headers = ('User-Agent', 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko')opener = urllib.request.build_opener()opener.addheaders = [headers]data = opener.open(add_url).read()data = data.decode('utf-8', 'ignore')# 获取酒店评论用户ID列表userid_temp=re.compile(r'<a target="_blank" rel="nofollow" href="/member/(.*?)" user-id="(.*?)" class="J_card">', re.DOTALL).findall(data)    userid=[None]*len(userid_temp)for i in range(0,len(userid_temp)):userid[i]=userid_temp[i][0]# 获取酒店评论用户的名字username = re.compile(r'<img title="(.*?)" alt=', re.DOTALL).findall(data)# 获取评价时间rate_time = re.compile(r'<span class="time">(..-..)', re.DOTALL).findall(data)# 获取单项评分rate_room = re.compile(r'<span class="rst">房间(.*?)<em class="col-exp">', re.DOTALL).findall(data)
#                 rate_envir = re.compile(r'<span class="rst">位置(.*?)<em class="col-exp">', re.DOTALL).findall(data)rate_service = re.compile(r'<span class="rst">服务(.*?)<em class="col-exp">', re.DOTALL).findall(data)# 获取总评分rate_total = re.compile(r'" class="item-rank-rst irr-star(.*?)0"></span>', re.DOTALL).findall(data)mink = min(int(len(userid)), int(len(rate_total)), int(len(rate_room)))# 获取用户评论user_comments= re.compile(r'<div class="J_brief-cont">(.*?)</div>',re.DOTALL).findall(data)user_comments=str(''.join(user_comments)) #类型转换user_comments=user_comments.strip() #去掉字符串中的换行符#print(user_comments)#将除酒店评论外的信息写入文件fileOp = open(fileOut, 'a', encoding="utf-8")for k in range(0, mink):fileOp.write('%s \t\t %s \t\t %s \t\t %s \t\t %s \t\t %s \t\t %s \t\t\n' % (hotelid, userid[k], username[k], rate_room[k], rate_service[k], rate_total[k], rate_time[k]))    fileOp.close()#将酒店评论写入另外的文件                    CommentsFile=open(FileName, 'a', encoding="utf-8")CommentsFile.write(user_comments.strip('\n'))CommentsFile.close()sleepNum=random.randint(0,2)time.sleep(sleepNum)#当访问过频的时候,大众点评网的发爬虫技术可能会临时封锁我们的ip,所以可以通过设定时间来调整爬取速度,建议慢速爬取。或者通过代理ip来避免反爬虫技术封锁IPprint(sleepNum)print("成功挖取第%s酒店的信息\n"%(count))# 异常处理:若异常,存储该url到新文本中,继续下一行的抓取except:print("第%s个酒店网址的信息抓取失败\n"%(websitenumber))#发生异常,无法成功爬取有用信息,抓取失败exceptionFile='exception.txt'file_except = open(exceptionFile,'a')file_except.write("%s\t\t%s"%(str(websitenumber),line)) #将爬取酒店信息时发生异常的网址保存起来#----------------------------------
#------------测试爬虫程序-------------
#----------------------------------
if __name__ == "__main__":urlspider.getHotelUrl(1) #爬取符合条件的酒店的主页网址fileIn = "HotelUrl.txt" #需要爬取酒店的网址getRatingAll(fileIn)#抓取酒店评论页面的间隔时间,单位为秒,可为0

(2)urlspider.py

本模块主要是爬取广州市天河区附近热门酒店的主页网址(酒店出现的顺序按评论数排名)。从程序中可以看出,我们需要从http://www.dianping.com/guangzhou/hotel/r22c354pno10 (最后一个 n 表示页数 1-50,并非为字母,通过改变 n 值可以遍历所有页面,找到所有酒店)中爬取每一页的所有酒店。在以访客方式访问时只能查看最多50页的酒店,不过已经足够了,毕竟评论数大于100条的其实并不多。爬取下来的酒店主页保存在“./HotelUrl.txt”。

代码如下:

    import urllib.request
import re
import os
def getHotelUrl(count):filename ='HotelUrl.txt'if os.path.exists(filename):
#         print("Yes")os.remove(filename)  print("正在获取广州市天河区附近热门酒店的URL,保存至HotelUrl.txt")for k1 in range(1,51):  tempurlpag = "http://www.dianping.com/guangzhou/hotel/r22c354p"+str(k1)+"o10" #下面对于当前页拿到每个酒店网址并加入队列headers = ('User-Agent', 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko')opener = urllib.request.build_opener()opener.addheaders = [headers]  op = opener.open(tempurlpag)  data= op.read().decode(encoding='UTF-8')  linkre = re.compile(r'data-shop-url="(.*?)"\r\n        data-hippo', re.DOTALL).findall(data)
#         print(linkre) for k2 in range(0, len(linkre)):  tempurlhotel = "http://www.dianping.com/shop/" + linkre[k2]   fileOp = open(filename, 'a', encoding="utf-8") fileOp.write(str(count)+"\t"+tempurlhotel+'\n')  fileOp.close()count+=1#print('目前是第:  %d  页的第: %d  个酒店,其地址是 :%s'%(k1+1,k2+1,tempurlhotel))  print('第:  %d  页抓取完成!'%k1) #----------------------------------
#--------测试抓取酒店URL程序------------
#----------------------------------
if __name__ == "__main__":count=1getHotelUrl(count)

运行结果:

(3)position.py
本模块主要用来爬取大众点评网的经纬度信息。大众点评网的地图位置很精确,但从HTML源码中却找不到坐标(经纬度)信息。本文将HTML中的js文本的POI参数转换成坐标,从而获取经纬度信息。参考于资料http://www.site-digger.com/html/articles/20111110/18.html,如有兴趣可仔细专研。

部分代码:

# coding: utf-8
# 解析大众点评地图坐标参数(POI)
def to_base36(value):#将10进制整数转换为36进制字符串if not isinstance(value, int):raise(TypeError("expected int, got %s: %r" % (value.__class__.__name__, value)))if value == 0:return "0"if value < 0:sign = "-"value = -valueelse:sign = ""result = []while value:(value, mod)= divmod(value, 36)result.append("0123456789abcdefghijklmnopqrstuvwxyz"[mod])return(sign + "".join(reversed(result)))
def getPosition(C):#解析大众点评POI参数digi = 16add = 10plus = 7cha = 36I = -1H = 0B = ''J = len(C)G = ord(C[-1])C = C[:-1]J -= 1for E in range(J):D = int(C[E], cha) - addif D >= add:D = D - plusB += to_base36(D)if D > H:I = EH = DA = int(B[:I], digi)F = int(B[I+1:], digi)L = (A + F - int(G)) / 2latitude = float(F - L) / 100000longitude = float(L) / 100000return longitude,latitude
#-----------------------------
#-----------测试程序-----------
#-----------------------------
if __name__ == '__main__':(longitude,latitude)=getPosition('IJGDHFZVIBRDHR')print("longitude:%s°E,latitude:%s°N"%(longitude,latitude))

(4) picture.py
本模块主要实现酒店图片的爬取。每个酒店的主页都会有几张该酒店的图片,我们将它们中的前5张(有些酒店少于5张)给爬取下来,存放到“./image”文件夹中。主要思路是将html中的图片对应链接给爬取出来,然后保存到该文件夹下即可。

import urllib.request
import redef getPicture(url,FileOut):webPage=urllib.request.urlopen(url)data = webPage.read()data = data.decode('UTF-8')picture_temp=re.compile(r'<img src="(.*?)%',re.DOTALL).findall(data)picture_url=picture_temp[0:5]#只需要获取前五张图片即可#print(picture_url)for i in range(0,5):web = urllib.request.urlopen(picture_url[i])#print(web)itdata = web.read()#print(itdata)f = open(FileOut+str(i+1)+'.jpg',"wb")f.write(itdata)f.close()#----------------------------------
#--------------测试程序---------------
#----------------------------------
if __name__ == "__main__":url = "http://www.dianping.com/shop/4672763"HotelName=u"广州四季酒店"#FileOut ='G:/EclipseWorkspace/Python/src/InternetWorm/Image/'+HotelNameFileOut ='.\\image\\'+HotelNamegetPicture(url,FileOut)

运行结果:

(5)PriceAndScores.py

本模块获取每个酒店的价格和星级评分。注意获取酒店价格的时候我把酒店网址“www.dianping.com/shop/*”改为“m.dianping.com/shop/*”。主要是有部分www端酒店主页的价格是动态网页,爬取较为麻烦,有兴趣你自己可以试一下,而m端的网页价格是静态网页,爬取较为简单。

程序如下:

import urllib.request
import re## 获取酒店名称和地址
def getPriceAndScores(url):url=url.replace('www.','m.')#爬取价格的时候需要将酒店的PC端(www.)的改为APP端(m.)#print(url)opener = urllib.request.build_opener()headers = ('User-Agent', 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko')opener.addheaders = [headers]data=opener.open(url).read()data= data.decode('utf-8')#ignore是忽略其中有异常的编码,仅显示有效的编码#获取酒店总评分scores=re.compile(r'<span class="star star-(.*?)"></span>',re.DOTALL).findall(data)#scores=str(' '.join(scores))scores = int(scores[0])/10#print(scores)#获取酒店价格price =re.compile(r'<span class="price">(.*?)</span>',re.DOTALL).findall(data)price = int(''.join(price ))#print(price )return price,scoresif __name__ == "__main__":url="http://www.dianping.com/shop/2256811"(price,scores)=getPriceAndScores(url)print(price)print(scores)

结果展示

1.每个酒店的基本信息及酒店评论用户的基本信息

2.每个酒店的用户评论

3.每个酒店的图片

4.hotel文件夹下

5.image文件夹下

本文仅献给那些想亲自快速实现网页爬虫的人类,对于大神来说本文不适合,对于搞研究的也不适合。因为本文仅适合“实现”而不是适合“讲原理”。十分感谢大家阅读这篇有点杂乱无章的笔记

Python3 实现大众点评网酒店信息和酒店评论的网页爬取相关推荐

  1. python大众点评网实训报告中的参考文献_python爬取大众点评网商家信息以及评价,并将数据存储到excel表中(源码及注释)...

    import requests from bs4 import BeautifulSoup import traceback # 异常处理 import xlwt # 写入xls表 # Cookie记 ...

  2. 大众点评网谈成功秘诀:明白用户感兴趣、需要和寻找的是什么

    如今的互联网用户,大多都能够熟练地使用搜索引擎查找到自己需要的信息,"浏览.输入.搜索"早已成为最普遍的上网场景.但是,并不是所有的互联网企业都懂得怎样通过掌握"场景&q ...

  3. jsoup实战之抓取大众点评网区域省份城市信息

    需求:从大众点评网抓取 所有区域,省份,城市信息 所使用技术:manve+jsoup.1.7.3+httpclient.4.3.3 pom.xml <project xmlns="ht ...

  4. 美团大众点评网:大数据勾勒“大钱景”

    近日,美团外卖APP通过大数据分析国内不同城市用户的外卖消费习惯,对外公布了各大城市的外卖消费特点.根据美团外卖对"各品类外卖订单量最高的城市"统计发现,除了订餐外,北京市鲜花蛋糕 ...

  5. 大众点评网的网站架构

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 大众点评 ...

  6. 大众点评网和爱帮网官司给我们的启示

    案件回顾:2007年年底,大众点评网认为其对数千家餐馆的点评内容享有独家著作权,爱帮网未经许可,擅自收录这些点评,构成侵权,函告爱帮网要求立即删除疑似侵权内容,但爱帮网复函坚称自己是搜索引擎类技术服务 ...

  7. 大众点评网公正性受质疑 被指评论常无故被删

    近日,记者接到来自宝山区瞿小姐的电话,称其刚开张的一家料理店受到大众点评网用户的恶意点评,却投诉无门.有意思的是,这个差评时间恰巧是瞿小姐与大众点评网宣传合作即将结束的时候出现的.与此同时,近期,记者 ...

  8. 一个价值一千五的外包项目!抓取大众点评的店铺信息!

    前言 今天在群里有人派外包的其中一个是抓取大众点评的店铺信息,价格一千五,三天内完成!很多刚学编程的小伙伴,应该觉得这个一千五也太容易拿了,相对于大众点评这个网站,其实不是像爬小说,爬表情包那样容易的 ...

  9. 大众点评网回应商家围攻:因诚信问题被暂停收录

    9 月 29 日消息,今日有网友在微博爆料称大众点评网与商家签订不平等合约,并实施竞价排名,因此上海总部遭到 200 家商户的集体围攻.对此,大众点评网对 TechWeb 发来声明,称美容美发机构京世 ...

最新文章

  1. 3天学会TensorFlow | 香港科技大学
  2. 【建站系列教程】1、前言
  3. OpenCV+yolov3实现目标检测(C++,Python)
  4. 关于might_sleep的一点说明---CONFIG_DEBUG_ATOMIC_SLEEP【转】
  5. XtraBackup全备与增量备份
  6. 全国计算机等级考试题库二级C操作题100套(第05套)
  7. 只能在测试中注射吗?
  8. 数据结构之栈的应用:树的层次遍历、图的广度优先遍历、OS的FCFS策略
  9. 台前与幕后的 5G 战争
  10. convenient functions in numpy
  11. 依赖编程内部知识的C语言习惯用法
  12. Shared library can't open object
  13. RHCE考试第一天之学习安排计划
  14. Unity 物理效果插件OBI使用记录,包含OBI-Rope绳索,OBI-Fluid,OBI-Cloth
  15. python打包xp系统_python打包的exe为啥在XP上提示“不是有效的WIN32程序”
  16. FME中WorkspaceRunner传参处理
  17. 网络知识总结二:物理层和链路层协议详解
  18. java中输出日历_Java打印日历表
  19. 论文阅读:Pixel-level Extrinsic Self Calibration of High Resolution LiDAR and Camera
  20. 高通Ziad Asghar:AI处理的重心从云端向边缘侧转移,智能手机是最佳平台 | MEET 2023...

热门文章

  1. 微软面经分享:如何更好地做好面试准备
  2. phpexcel列数太多,【PHPEXECL】关于使用phpExecl导出数据时,列数超过26个报错问题
  3. Python+经济学:成本函数与图像
  4. Aria2c命令行下载路径
  5. 经典 【操作系统实验】 实验六 设备驱动程序 RH5 2.6.18 + 2.6.32 内核
  6. Oracle数据库•笔记
  7. PKUSC2022 游记
  8. ESP8266 Deep-Sleep 模式下的唤醒方式
  9. win10远程计算机管理,教你如何使用Win10远程桌面控制他人电脑?,爱纯净官网
  10. 远程桌面黑背景解决办法