携程酒店数据爬取2020.5

1. 开题

目前网上有好多爬取携程网站的教程,大多数通过xpath,beautifulsoup,正则来解析网页的源代码。然后我这个菜b贪方便,直接copy源码的xpath,paste在xpath helper改改规则。xpath helper识别出结果后,我就已经看到了成功的希望,xpath真香。
然而,意想不到的是,在进行测试时,却匹配不出任何结果,我手中的鸡腿(xpath)就不香了,曾一度怀疑,是我水平太菜了,没写正确,然后一直回去学xpath知识,一边学啊,一边测试,甚至中途换了beautifulsoup,正则,selenium(建议不要用selenium,打开网站时候会自动跳转到携程账号登录页面,估计是携程反爬的设置)。直到后来才发现解析的源代码根本就没包含我想要的信息(酒店名称,酒店地址这些东西,携程有可能设置了反爬),这也说明了,我水平真的菜,才会一直没发现源代码的错误(我暂且认为源代码中没有显示酒店名称,地址这类信息)

>>> hotel_name = html.xpath('//p[@class="hotel_item_htladdress"]/text()')
>>> print(hotel_name)
[]
>>> hotel_name = html.xpath('//li[@class="hotel_item_name"]/h2')
>>> print(hotel_name)
[]

2.人肉搜索器的变化

因为写不出来代码,而业务上需要信息,故我这个菜b只能一边Ctrl C + Ctrl v,手指都快抽筋了,才把部分数据给复制下来,最后只能祭出GitHub大法了

在看完了几个大佬写的代码,看不懂还是看不懂。
但是抄,我是专业的,这孩子从小就是抄袭砖家,Ctrl A + Crtl c + crl v 三键下去,一气呵成。
感谢让抄的老哥(author: songwei,附上他的网址:https://github.com/songweiwei/pachong/blob/master/main.py#L29)
在抄完之后要干吗?改啊!
要怎么改啊?针对这一点,我是会的。
同学们,小葵花妈妈开课了,孩子会抄,不会改,怎么办呢?多半是上课没好好学,打一顿就好了。咳咳,偏题了。
首先呢,我们先看看携程网站的网址,它的网址是固定了,也就是不管你翻到第几页,它的网址一成不变。稍微学过点爬虫的同学都知道,我们爬取网站都是通过网址的页数进行翻页,那没能通过页数进行解析,怎么办呢?

此时,百度就是你的老师,你要熟练地打开网站,敲上你最喜欢的网址,准备好纸巾…呸呸呸,又飙车了。
本菜b饱览群书(抄袭大佬的观点),在网页反馈的信息中后面添加p1,p2便可实现翻页的功能:
第一页:https://hotels.ctrip.com/hotel/guangzhou32/p1
第二页:https://hotels.ctrip.com/hotel/guangzhou32/p2

看到这里,细心的同学就会想到,楼主这个菜b不是刚刚才说完,网页的源代码不是没有想要的信息(酒店名称,地址)吗?即便会翻页,那网页的源代码没信息,还翻个屁啊?
对,没错,翻个屁,就是没什么卵用。
于是,我们要从其他地方入手。
楼主这个菜b又饱览群书,通过百度老师,猛然发现@icmp_no_request大神的帖子(https://blog.csdn.net/pandalaiscu/article/details/87644235),于是乎,我在抄的路上又迈开一大步,学会通过接口获取数据。
在AjaxHotelList.aspx文件发现了存储信息的位置,其格式是json,其中hotelPositionJSON里面存储了25条数据(一个网页只显示25条数据)

hotelPositionJSON中的url是打开酒店详细信息的“钥匙”,能查看酒店的具体信息(如介绍,设施等情况)

但在打开酒店具体信息的网址后,我们会发现一些问题,如下图中的原始网站只显示“联系方式”,这需要手工点击“联系方式”字段才能显示电话号码,若是通过xpath解析,也只是出现个“联系方式”的字段,因此这一块需要解析原网站的网页元素,针对这一块内容,我这边是用正则来写的,没错,“正则”真香。

其次对于酒店品牌和集团的获取,我们这里用回了xpath进行解析(因为网页的源代码已经有我们想要的信息)。由于携程的品牌名称显示在网站的首头,而部分网站没有品牌名称(如第一种和第二种所示),只有第三钟包含我们想要的品牌名称字段(酒店品牌:希尔顿)。此外部分酒店网页也是没有显示酒店集团的元素,若是通过xpath定位,有可能导致匹配信息错误。
针对这些问题,我们通过判断返回的xpath值若是为空,则不存在该元素来规避数据错误值

3.开始征程之路

作好了以上的解析后,我们可以开始写(改大神的)代码了
3.1 构建存储器

#构建数组存储数据
#构建数组存储数据
hotel_name = [] #酒店名称
hotel_address = []  #酒店地址
hotel_iphone = []   #酒店电话
hotel_brand = [] #酒店品牌
hotel_business = [] #酒店所属集团

3.2 构建请求头
其中user-agent用了fake_useragent包

url = "https://hotels.ctrip.com/Domestic/Tool/AjaxHotelList.aspx"
headers = {'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8','Origin': 'https://hotels.ctrip.com','Referer': 'https://hotels.ctrip.com/hotel/guangzhou32','accept': '*/*','user-agent': str(UserAgent().random)
}

3.3 构造请求字段

    #page是页码(翻页),广州cityID是32(北京cityID是1)formData = {'cityId': 32,  #城市id号'page': 1   #页码}

3.4 发起网站请求

    # 发起网络请求r = requests.post(url, data=formData, headers=headers)r.raise_for_status()r.encoding = r.apparent_encoding    #防止出现乱码现象

3.5 解析网站元素

       # 解析 json 文件,提取酒店数据js=json.loads(r.text)json_data = json.loads(r.text)['hotelPositionJSON']for item in json_data:hotelName = item['name']hotelAdress = item['address']hotelUrl = item['url']hotel_name.append(hotelName)hotel_address.append(hotelAdress)#在首页打开酒店url,获取电话号码,其中电话隐藏了,因此用正则直接提取new_hotelUrl = "https://hotels.ctrip.com" + item['url']req = requests.get(new_hotelUrl,headers=headers)page = req.textpattern = re.compile('<span id="J_realContact" data-real="(.*?)&nbsp;&nbsp',re.S)item_iphone = pattern.findall(page)hotel_iphone.append(item_iphone)    #正则写入数据的形式是列表,这里再次把列表数据写入列表#xpath解析酒店品牌+集团html = etree.HTML(page)hotelBrand = html.xpath('//*[@id="base_bd"]/div[2]/a[3]/text()')if fnmatch(str(hotelBrand),"*区*"):hotel_brand.append("无")elif len(hotelBrand) ==0:hotel_brand.append("无")else:hotel_brand.append(hotelBrand)hotelBusiness = html.xpath('//*[@id="hotel_info_comment"]/div/span/text()')if len(hotelBusiness) == 0:hotel_business.append("无")else:hotel_business.append(hotelBusiness)

3.6 存储数据

#储存
wb = workbook.Workbook()
ws = wb.active
ws.append(["酒店名称","地址",'电话号码','酒店品牌','酒店集团'])for i in range(0,len(hotel_name)):ws.append([hotel_name[i],hotel_address[i],hotel_iphone[i][0],hotel_brand[i][0],hotel_business[i][0]])
#存储位置:C:\Users\Administrator
wb.save("携程酒店数据.xlsx")

4.结果展示与不足反思

本次代码由于业务和时间关系,只解析了酒店名称,地址,电话号码,酒店品牌和集团这五个字段,因此各位小伙伴若是要解析其他信息,您可以通过我这篇文章的代码思路继续进行解析。
最后我反思一下本次代码的不足:

  1. 没有设置ip代理池,若是数据量大,必然会封ip。后期用代理ip进行测试,发现一个代理ip短时间内抓100条数据就失效了
  2. 获取25条数据时,需要打开25个网页,也就说打开一个网页需要一秒时间,若是要爬取大量的数据,其时间耗费长。后期仍需努力学习啊。

5.完整代码

import requests
from lxml import etree
from fake_useragent import UserAgent
import os, re, json, traceback,random,time
from openpyxl import workbook  # 写入Excel表所用
from fnmatch import fnmatch#启用时间
start = time.time()#构建数组存储数据
hotel_name = [] #酒店名称
hotel_address = []  #酒店地址
hotel_iphone = []   #酒店电话
hotel_brand = [] #酒店品牌
hotel_business = [] #酒店所属集团#构建请求头
url = "https://hotels.ctrip.com/Domestic/Tool/AjaxHotelList.aspx"
headers = {'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8','Origin': 'https://hotels.ctrip.com','Referer': 'https://hotels.ctrip.com/hotel/guangzhou32','accept': '*/*','user-agent': str(UserAgent().random)
}#主代码
for i in range(1,10):print("爬取第%d页" %i )proxy = ["103.233.152.140:8080","222.249.238.138:8080","101.4.136.34:8080","58.253.66.47:8080"]proxies = {"http": str(random.choice(proxy))}#page是页码(翻页),广州cityID是32(北京cityID是1)formData = {'cityId': 32,'page': i}# 发起网络请求r = requests.post(url, data=formData, headers=headers,proxies=proxies)r.raise_for_status()r.encoding = r.apparent_encoding    #防止出现乱码现象# 解析 json 文件,提取酒店数据js=json.loads(r.text)json_data = json.loads(r.text)['hotelPositionJSON']for item in json_data:hotelName = item['name']hotelAdress = item['address']hotelUrl = item['url']hotel_name.append(hotelName)hotel_address.append(hotelAdress)#在首页打开酒店url,获取电话号码,其中电话隐藏了,因此用正则直接提取new_hotelUrl = "https://hotels.ctrip.com" + item['url']req = requests.get(new_hotelUrl,headers=headers)page = req.textpattern = re.compile('<span id="J_realContact" data-real="(.*?)&nbsp;&nbsp',re.S)item_iphone = pattern.findall(page)hotel_iphone.append(item_iphone)    #正则写入数据的形式是列表,这里再次把列表数据写入列表#xpath解析酒店品牌+集团html = etree.HTML(page)hotelBrand = html.xpath('//*[@id="base_bd"]/div[2]/a[3]/text()')if fnmatch(str(hotelBrand),"*区*"):hotel_brand.append("无")elif len(hotelBrand) ==0:hotel_brand.append("无")else:hotel_brand.append(hotelBrand)hotelBusiness = html.xpath('//*[@id="hotel_info_comment"]/div/span/text()')if len(hotelBusiness) == 0:hotel_business.append("无")else:hotel_business.append(hotelBusiness)#储存
wb = workbook.Workbook()
ws = wb.active
ws.append(["酒店名称","地址",'电话号码','酒店品牌','酒店集团'])for i in range(0,len(hotel_name)):ws.append([hotel_name[i],hotel_address[i],hotel_iphone[i][0],hotel_brand[i][0],hotel_business[i][0]])
#存储位置:C:\Users\Administrator
wb.save("携程酒店数据.xlsx")#结束
end = time.time()
print("耗时(分钟):",(end - start)/60)
print("爬取页数:",len(hotel_name)/25)

携程酒店数据爬取2020.5相关推荐

  1. 对携程酒店用户评价爬取

                                                                                                        ...

  2. 爬取携程和蚂蜂窝的景点评论数据\携程评论数据爬取\旅游网站数据爬取

    本人长期出售超大量微博数据.旅游网站评论数据,并提供各种指定数据爬取服务,Message to YuboonaZhang@Yahoo.com.同时欢迎加入社交媒体数据交流群:99918768 前言   ...

  3. Java数据爬取——爬取携程酒店数据(二)

    在上篇文章Java数据爬取--爬取携程酒店数据(一)爬取所有地区后,继续根据地区数据爬取酒店数据 1.首先思考怎样根据地域获取地域酒店信息,那么我们看一下携程上是怎样获得的. 还是打开http://h ...

  4. Java数据爬取——爬取携程酒店数据(一)

    最近工作要收集点酒店数据,就到携程上看了看,记录爬取过程去下 1.根据城市名称来分类酒店数据,所以先找了所有城市的名称 在这个网页上有http://hotels.ctrip.com/domestic- ...

  5. 爬虫第六课:爬取携程酒店数据

    首先打开携程所有北京的酒店http://hotels.ctrip.com/hotel/beijing1 简简单单,源代码中包含我们需要的酒店数据,你以为这样就结束了?携程的这些数据这么廉价地就给我们得 ...

  6. JAVA爬虫爬取携程酒店数据selenium实现

    在爬取携程的时候碰到很多的壁垒,接下来分析所有过程 1.根据以往经验最初想到用jsoup去解析每个HTML元素,然后拿到酒店数据,然后发现解析HTML根本拿不到id为hotel_list的div,所以 ...

  7. js逆向之携程酒店房价抓取

    团队持续招人,app逆向方向,私聊.2019-05-11 修复携程eleven参数改版问题 1 在调用require的时候判断是不是参数是不是path,如果是抛出异常 2 重新window的构造方法的 ...

  8. Python3+Scrapy通过代理爬取携程酒店数据

    目标:通过爬取酒店信息保存至本地mysql数据库中 目标网址:https://hotels.ctrip.com/hotel/Haikou42 首先新建scrapy项目 命令行输入:crapy star ...

  9. 破解携程中文验证码爬取机票价格数据

    国内机票预定APP携程处于垄断地位,但是携程有反爬虫策略,对于密集的查询请求会要求验证,验证操作有两次,一次是拖动验证,一次是点选中文,selenium+webdriver可以轻松绕过这一反爬虫设置. ...

最新文章

  1. python学习随笔--web框架
  2. probit概率单位回归分析
  3. .NET Core微服务系列基础文章索引(目录导航Final版)
  4. 解决Ubuntu与Windows之间无法复制粘贴问题
  5. 把度分秒的经纬度转换成十进制的经纬度的工具类
  6. 基于U-net的肝脏肿瘤分割实战(Pytorch实现)
  7. Docker的Hadoop-Hbase的 Docker Hub文档
  8. matlab 找到数组中第一个不连续点_MATLAB新手入门篇1(基础)
  9. 让蒲公英路由器支持IPv6
  10. 【mysql】mysql 导出全库表结构,并排除指定库
  11. PHP扭蛋机原理,微信小程序 扭蛋抽奖机css3动画实现详解
  12. -xms -xmx无效
  13. DCOS到底是啥?看完这篇你就懂了~
  14. VMware安装后界面显示为英文
  15. Microsoft Excel 教程:如何在 Excel 单元格中设置文本格式?
  16. oracle bulk collect into,BULK COLLECT INTO
  17. 优质免费在线学习网站
  18. 自定义拍照时 拍照界面_摄影技巧,拍照时模特的眼睛应看向哪里?不同的眼神方向有何区别...
  19. mysql lsof打开数过多_lsof 查看进程打开的文件情况 df -h 磁盘空间满的异常处理...
  20. 计算机动画专业教学大纲,3d-Max动画制作课程教学大纲

热门文章

  1. python中 for i in range(10)_在Python语句: for i in range(10) : ...... 中,循环终值是( )。...
  2. mysql drop后回收站怎么恢复_回收站清空了怎么恢复
  3. mvbox6.1官方版 7.1.0.4
  4. 解决:win10输入法不显示在状态栏开机只能输入英文修改切换输入法快捷键
  5. 维度和指标(metrics and dimensions)
  6. 三极管当成开关来使用,电路及其参数计算
  7. 计算机休眠usb充电,三星笔记本Win8如何开启USB接口休眠、关机时充电
  8. go本地缓存bigcache
  9. 怎样将CAD图纸转换成Word?这个方法手机也能用
  10. 微信活动链接如何创建?门店拓客引流活动链接制作