Python爬虫爬取酒店评价(携程)

Python爬虫爬取携程酒店评价

审查携程酒店评价页面

最经有个需求是爬携程上某酒店的用户评价,在审查评论界面后发现了以下请求,贴一下:

https://hotels.ctrip.com/Domestic/tool/AjaxHotelCommentList.aspx?
MasterHotelID=5209137&hotel=5209137&NewOpenCount=0&AutoExpiredCount=0&RecordCount=1697&
OpenDate=&card=-1&property=-1&userType=-1&productcode=&keyword=&roomName=&orderBy=2&
currentPage=2&viewVersion=c&contyped=0&
eleven=5c8db5e27d24f88e0113e8d0b3632dc2d49900f13f4acd4acda67302282a601b&
callback=CASDmoihBhHGlfxap&_=1557127661607

其中MasterHotelID 、 hotel 就是要查找的酒店id了 这个不难获取是在不行看一下超链接的url里就有这个id。
当时点了几个下一页之后发现currentPage 就是控制显示第几页的这么一个参数,好开心。
然后尝试修改该参数…

你们能想象在更改了currentPage 后什么都没发生面对空白界面时候的那种无力感吧。
无奈之中 发现eleven这个参数有点奇怪,稍微查了一下就知道这个东西不简单

对于爬虫小白的我来说,面对携程反爬工程师设下的这么一个捕虫网实在是无力。
如果是曾经爬过携程的 其他爬虫们肯定遇到过这个东西 其根本原因呢 就是携程那搞了一个
oceanball 简而言之呢就是一个js文件最终生成 动态的eleven 有了这个才能正确的访问url

当然因为是js生成的eleven 而oceanball这个文件也是能获取到的,有能力的爬虫大佬们能尝试从源头获取这个eleven,其中遇到的坑应该会不少,而我这的需求又比较紧,那不如换个思路

变换思路,从手机端界面着手

在无意中我发现了一个可能还没被携程工程师发现的小洞口。
先上url

http://m.ctrip.com/html5/hotel/HotelDetail/dianping/5209137.html

emm…这个就是一个用于手机端展示的界面,从pc浏览器也一样能访问,当我看到这个东西的时候,再次两样放光!!

而且界面很干净,几乎只有评论
Python爬虫爬取酒店评价(携程)
对吧,感觉离希望不远了吧,我当时也是这么想的~

看到这你就又知道 emm 这虫又被坑了,当然 如果那么简单就爬到了 我就不写这文章当个防坑贴了啊

其实呢数据是能拿到的 只是你会发现数据只有几条 不全
这是为什么呢

其实很好理解,这个毕竟是给手机端使用的,当然不可能一下子全部加载完成啊,这个界面是动态加载的!!

那么这个就很sillyB 了 我难道还要模拟下滑?
不存在的,这种事情还得模拟?他既然异步加载肯定是要有请求的!!!那么找!请!求!

Python爬虫爬取酒店评价(携程)
多往下滑动一下就能发现,每次加载新内容的时候都会发送这样一个请求

请求地址
http://m.ctrip.com/restapi/soa2/16765/gethotelcomment?_fxpcqlniredt=09031144211504567945

经常做GET请求的我忽然发现 en? 这个是post请求诶,赶紧找一下参数

Python爬虫爬取酒店评价(携程)
呐,看呀 多熟悉的参数 多熟悉的id
贴一下,尊重一下

{
  "hotelId":5209137,
  "pageIndex":8,
  "tagId":0,
  "pageSize":10,
  "groupTypeBitMap":2,
  "needStatisticInfo":0,
  "order":0,
  "basicRoomName":"",
  "travelType":-1,
  "head":{
  	"cid":"09031144211504567945",
  	"ctok":"",
  	"cver":"1.0",
  	"lang":"01",
  	"sid":"8888",
  	"syscode":"09",
  	"auth":"",
  	"extension":[]
  	}
  }

看到这心情舒畅,什么叫pageIndex!!什么叫pageSize!! 多么清香
改! pageIndex = 1 pageSize = 999999999

又一次希望的曙光…好了,又是熟悉的场景…

来看一下错误代码吧

{
	"ResponseStatus":{
	"Timestamp":"/Date(1557126818926+0800)/",
	"Ack":"Success",
	"Errors":[],
	"Extension":[
		{"Id":"request-id","Value":"a4ad2cf2-d20b-438c-ad91-08a110b97c93"},
		{"Id":"CLOGGING_TRACE_ID","Value":"8440858090837212398"},
		{"Id":"RootMessageId","Value":"921812-0a1c5366-432535-599929"}]
	}
}

看到了吗 你成功的访问了我 但我就是不给你看,诶,气死你!

我感觉我这小虫子 已经徘徊在 自己碾死自己的边缘了。

心灰意冷的把 pageIndex 和 pageSize 都改成和原参数一样的数值,再试试吧

当黑窗口出现了梦寐以求的文字的时候,一束光…(手动敲醒自己)

不,这次是真的!
Python爬虫爬取酒店评价(携程)
看到这些,默默的检查了一遍,发现emmm好像就是这样没错呢

至此,也算是不需要和携程的反爬工程师斗智斗勇就能爬到酒店评论数据了。

当然这块地方的漏洞估计早晚是会被堵上的,现在是19年的5月初,有前辈在17年就通过这种方式爬过数据。至于之后…反正我这个需求是一次性的,哼哼!

代码实现

这边的代码呢 我也就只放到上述步骤了,作为学习笔记放在这。至于数据处理等内容,由于和爬虫没什么关系,就不放在这边了。

from urllib import request
import json

def getResponse(url):

    data = {"hotelId":5209137,"pageIndex":1,"tagId":0,"pageSize":10,"groupTypeBitMap":2,"needStatisticInfo":0,"order":0,"basicRoomName":"","travelType":-1,"head":{"cid":"09031144211504567945","ctok":"","cver":"1.0","lang":"01","sid":"8888","syscode":"09","auth":"","extension":[]}}
    data = json.dumps(data).encode(encoding='utf-8')
    
    
    header_dict = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko',"Content-Type": "application/json"}

    url_request = request.Request(url=url,data=data,headers=header_dict)
    print("这个对象的方法是:",url_request.get_method())

    url_response = request.urlopen(url_request)
    
    return url_response

http_response = getResponse("http://m.ctrip.com/restapi/soa2/16765/gethotelcomment?_fxpcqlniredt=09031144211504567945")

data = http_response.read().decode('utf-8')
print(data)

如上代码呢只是获取了第一页10条的数据,要获取很多,循环吧,要怎么停自然也是很简单,通常的请求既然考虑了正确返回 肯定也会有错误返回 或者默认返回 而这些都是有规律的

写过接口的人都不会不了解其中的道道。

好了,核心差不多就是这些了,至于怎么优化,大佬们,加油!