前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >捅马蜂窝啦!!!

捅马蜂窝啦!!!

作者头像
龙哥
发布2019-04-25 13:52:14
8300
发布2019-04-25 13:52:14
举报
文章被收录于专栏:Python绿色通道Python绿色通道

马蜂窝之旅游问答

上图为马蜂窝的旅游问答页(http://www.mafengwo.cn/wenda/area-10206.html?sFrom=mdd),通过不断点击加载更多发送ajax请求更新页面,通过抓包,可以得到获取回答内容的接口,这是一个get请求,通过更换page来不断的获取新的内容。

不过最大请求page为24,当page>24时,会返回空值。一共只能返回500不到的数据量。所以可以自己在搜索是添加标签,如中国澳门美食。

这样就可以增加获取到的数据量噢。

代码语言:javascript
复制
import requestsurl = "http://www.mafengwo.cn/qa/ajax_qa/more"querystring = {"type":"0","mddid":"10206","tid":"","sort":"1","key":"","page":"1","time":""}headers = {    'Pragma': "no-cache",    'Accept-Encoding': "gzip, deflate",    'Accept-Language': "zh-CN,zh;q=0.9",    'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",    'Accept': "application/json, text/javascript, */*; q=0.01",    'Referer': "http://www.mafengwo.cn/wenda/area-10206.html?sFrom=mdd",    'X-Requested-With': "XMLHttpRequest",    'cache-control': "no-cache",    'Postman-Token': "b0c95558-c509-4752-b49a-d80086e0a15a"    }response = requests.request("GET", url, headers=headers, params=querystring)print(response.text)

马蜂窝之游记

以成都游记举个栗子(http://www.mafengwo.cn/travel-scenic-spot/mafengwo/10035.html)。马蜂窝的游记有两个接口,一个是最热游记,一个是最新游记。最热游记只给提供300页共3000条;最新游记则是有多少给你看多少。所以只需爬取最新游记就可以全部抓取。

这是一个post请求,一共有十个参数,_sn参数可以不用更换,就可以不断改变page获得内容。

也就是说,将page赋值2534的同时不改变_sn的值也可以获取到游记内容。

代码语言:javascript
复制
import requestsurl = "http://www.mafengwo.cn/gonglve/ajax.php"querystring = {"act":"get_travellist"}payload = "mddid=10035&pageid=mdd_index&sort=2&cost=0&days=0&month=0&tagid=0&page=2534&_ts=1553332896149&_sn=a4ad17d822"headers = {    'Pragma': "no-cache",    'Origin': "http://www.mafengwo.cn",    'Accept-Encoding': "gzip, deflate",    'Accept-Language': "zh-CN,zh;q=0.9",    'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",    'Content-Type': "application/x-www-form-urlencoded; charset=UTF-8",    'Accept': "application/json, text/javascript, */*; q=0.01",    'Cache-Control': "no-cache",    'X-Requested-With': "XMLHttpRequest",    'Referer': "http://www.mafengwo.cn/travel-scenic-spot/mafengwo/10035.html",    'cache-control': "no-cache",    'Postman-Token': "74506c28-c314-4238-b55d-b781360f6a2d"    }response = requests.request("POST", url, data=payload, headers=headers, params=querystring)print(response.text)

马蜂窝之美食

关于美食篇,可显示的页面数也做了限制,只能显示20页共300条数据(http://www.mafengwo.cn/cy/10035/)

不过可以通过拼凑url分区获取,以获得大量数据,其中特色和分类这两类不能同时选择,因为它们的id位于同一位置(0-0-id-0-0-1);而商圈类的id位于第二位(0-id-0-0-0-1);所以可以通过在第二位和第三位平凑不同的id号来获取数据,比如(0-46549-7654-0-0-1)来定位春熙路的川菜。

在不断点击下一页,可以得知这是一个get请求,仅改变第六位(0-id-id-0-0-page)来翻页,如春熙路川菜第十五页:http://www.mafengwo.cn/cy/10035/0-46549-7654-0-0-15.html

当然如果想要得到某家店的详细信息,一定需要进入其详情页。(ul.poi-list > li:nth-child(1) > div.title > h3 > a)

代码语言:javascript
复制
import requestsurl = "http://www.mafengwo.cn/cy/10035/"headers = {    'Connection': "keep-alive",    'Upgrade-Insecure-Requests': "1",    'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",    'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",    'Referer': "http://www.mafengwo.cn/cy/10035/0-0-9472-0-0-1.html",    'Accept-Encoding': "gzip, deflate",    'Accept-Language': "zh-CN,zh;q=0.9",    'cache-control': "no-cache",    'Postman-Token': "3670100a-7683-4e61-aeb1-b71bd4f1d6bd"    }response = requests.request("GET", url, headers=headers)print(response.text)

在这个页面可以得到各个标签的id~~~

马蜂窝之蜂蜂点评

通过抓取美食访问各个商户的详情页,发现评论数据都放在了蜂蜂点评中(http://www.mafengwo.cn/poi/87950.html)

要抓取它的点评数据还是挺困难的,而且它只显示五页

点击下一页,一共五次得到下面的请求,所有的评论数据都在这一类url中。在这里就和游记有一些不同,这里的_sn必须和params以及_ts保持一致。如果不一致就会返回空值。所以要获得评论数据就必须找出_sn是如何生成的。

找到这个js文件http://js.mafengwo.net/js/hotel/sign/index.js?1552035728。在第363行和第364行打上断点,然后点击下一页。

第363行会生成一个json变量 _0xe7fex39。在第364行,首先运行这一部分:(JSON[__Ox2133f[60]](_0xe7fex39) + _0xe7fex34)即生成一个字符串类型的变量:"{"_ts":"1553500557401","params":"{\"poi_id\":\"87950\",

\"page\":1,\"just_comment\":1}"}c9d6618dbc657b41a66eb0af952906f1"

然后再通过函数_0xe7fex2生成32位的字符串;最通过slice(2,12)函数对其进行切割,获得2-12的字符串,这个就是_sn的值。

查找这个函数发现_0xe7fec函数将变量生成一个长度为4的数组;在通过_0xe7fex10函数将数组生成对应的字符串;最后将_0xe7fex15拼接起来。

而拼接后的这串字符的2-12位就是_sn值。这整个加密过程就是常说的md5加密。右边的加密结果和_0xe7fex15拼接起来的字符串是完全一样的;

此时生成的_sn值bc28b3ed57就是对参数进行md5加密取2-12位的结果。

得到_sn值后,评论数据就可以很容易就得到。这里要注意的是,在请求是必须把url拼接完整,否则只会返回一点点数据。另外在生成_sn时,参数qdata必须保持一致,是双引号就是双引号,有反斜杠就要有反斜杠,不然得不到正确的_sn值。

代码语言:javascript
复制
import hashlibimport requestsdef par(t):    hl = hashlib.md5()    hl.update(t)    return hl.hexdigest()[2:12]page=1t=1553500557401qdata='{"_ts":"'+str(t)+'","params":"{\\"poi_id\\":\\"87950\\",\\"page\\":'+str(page)+',\\"just_comment\\":1}"}c9d6618dbc657b41a66eb0af952906f1'sn=par(qdata.encode('utf-8'))print(sn)
url = "http://pagelet.mafengwo.cn/poi/pagelet/poiCommentListApi?"
querystring = {"callback":"jQuery181011036861119045205_1553502048335",               "params":"%7B%22poi_id%22%3A%2287950%22%2C%22page%22%3A{}%2C%22just_comment%22%3A1%7D".format(str(page)),               "_ts":t,               "_sn":sn,               "_":t+1}
headers = {    'Referer': "http://www.mafengwo.cn/poi/87950.html",    'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"    }for key,value in querystring.items():    url=url+key+'='+str(value)+'&'url=url[:-1]response = requests.request("GET", url, headers=headers)print(response.text)

既然可以构建参数访问前五页的数据,那是否可以通过这种方式访问第六页呢?将page改为6是可以成功获取到数据的,抽取page=6的第一条评论的部分和第五面第一条对比一下。果真是想太多。。。。。。

马蜂窝之景点

关于马蜂窝的景点数据,也是需要各个参数和_sn保持一致的。这里以四川的景点为例说明。

先抓包,在xhr中点击一次下一页,就有生成三个页面。其中所需要的内容在router.php中。

跟之前一样,在第363行和第364行打上断点,对变量进行md5加密。

可以看到下列结果和上图的_sn值是完全一样!

代码语言:javascript
复制
import hashlibimport requestsdef par(t):    hl = hashlib.md5()    hl.update(t)    return hl.hexdigest()[2:12]page=3t=1553503246638qdata = '{"_ts":"' + str(t) + '","iMddid":"12703","iPage":"' + str(page) + '","iTagId":"0","sAct":"KMdd_StructWebAjax|GetPoisByTag"}c9d6618dbc657b41a66eb0af952906f1'sn=par(qdata.encode('utf-8'))print(sn)#e08b27d91furl = "http://www.mafengwo.cn/ajax/router.php"data = {    'sAct': 'KMdd_StructWebAjax|GetPoisByTag',    'iMddid': '12703',    '_ts': t,    'iPage': page,    'iTagId': '0',    '_sn': sn}headers = {    'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"    }response = requests.request("POST", url, headers=headers,data=data)print(response.text)

再比如这个页面,当你点击时就会生成,其_sn也通过md5生成。虽然这个页面没有返回什么需要的内容,但可以巩固一下加密方法。

马蜂窝之当地玩乐

关于马蜂窝的当地玩乐部分(http://www.mafengwo.cn/localdeals/0-0-M12703-0-0-0-0-0.html),没有页数的限制,可以不断的请求下一页。

每点击一次下一页,在xhr中就会新生成两个页面,其中返回数据的url是一个非常简单的get请求,只需要改变page的值即可。

请求第37页,可以看到返回的结果和页面是完全一样的

代码语言:javascript
复制
import requestsurl = "http://www.mafengwo.cn/localdeals/ajax_2017.php"querystring = {"act":"GetContentList","tag_group[9521][]":"all","tag_group[9365][]":"all","reduce[]":"all","booking_days[]":"all","from":"NaN","kw":"","to":"M12703","salesType":"NaN","page":"37","group":"NaN","sort":"smart","sort_type":"desc","limit":"20","booking_days%5B%5D":"all","reduce%5B%5D":"all","tag_group%5B9365%5D%5B%5D":"all","tag_group%5B9521%5D%5B%5D":"all"}headers = {    'Accept-Language': "zh-CN,zh;q=0.9",    'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",    'Accept': "application/json, text/javascript, */*; q=0.01",    'cache-control': "no-cache",    'Postman-Token': "c5ece4e3-cf93-4522-a9a6-0b06397ec81d"    }response = requests.request("GET", url, headers=headers, params=querystring)print(response.text)

马蜂窝之验证码

打开酒店预订页面时,会有一个验证码跳出,再进入酒店页面前必须要先通过这个验证码。

验证码在index这个页面,通过get请求将验证码图片保存到本地,同时需要保存这个网页的cookie。因为在发送验证码的时候需要这个cookie来提供依据,可以理解为一张图片对应一个cookie;通过cookie来验证是否是这张图片。

现在输入正确的验证码,找到如下所示的这个url。这个url通过ccode,_ts,_sn三个参数拼接而成;ccode就是你要输入的验证码,_ts就是时间戳。现在只需要把_sn构建出来就可以了。

还是在第363和364打上断点,此时的_0xe7fex39为{ccode:"fisy",_ts:1553507570004};然后对加上_0xe7fex34的字符串进行md5加密即可。

对比验证码验证参数,可以看到是完全一样的。

代码语言:javascript
复制
import hashlibimport requestsimport timedef par(t):    hl = hashlib.md5()    hl.update(t)    return hl.hexdigest()[2:12]headers = {    'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"    }purl='http://www.mafengwo.cn/hotel/captcha/index'html=requests.get(purl,headers=headers)with open('img.jpg', 'wb') as f:    image = html.content    f.write(image)    f.close()code = input("请输入验证码")o=html.cookiesPHPSESSID=o['PHPSESSID']mfw_uuid=o['mfw_uuid']oad_n=o['oad_n']t=int(time.time()*1000)data='{"_ts":"'+str(t)+'","ccode":"'+code+'"}c9d6618dbc657b41a66eb0af952906f1'sn=par(data.encode('utf-8'))print(sn)data={'ccode': code,'_ts': str(t),'_sn': sn}cookie="PHPSESSID={0}; mfw_uuid={1}; oad_n={2}; uva=s%3A78%3A%22a%3A3%3A%7Bs%3A2%3A%22lt%22%3Bi%3A1552989105%3Bs%3A10%3A%22last_refer%22%3Bs%3A6%3A%22direct%22%3Bs%3A5%3A%22rhost%22%3Bs%3A0%3A%22%22%3B%7D%22%3B; __mfwurd=a%3A3%3A%7Bs%3A6%3A%22f_time%22%3Bi%3A1552989105%3Bs%3A9%3A%22f_rdomain%22%3Bs%3A0%3A%22%22%3Bs%3A6%3A%22f_host%22%3Bs%3A3%3A%22www%22%3B%7D; __mfwuuid=5c90bbb0-8d5f-5df8-50bb-acf3b2f39a12; UM_distinctid=1699904eca797-0b6edef1fe2585-36637902-13c680-1699904eca868e; ad_widget_footer_20190314formal_2_other=1%2C1vuh0fz; __mfwothchid=referrer%7Cwww.mafengwo.cn; __mfwlv=1553501567; __mfwvn=6; CNZZDATA30065558=cnzz_eid%3D20394471-1553047971-%26ntime%3D1553506977; __mfwlt=1553508203".format(PHPSESSID,mfw_uuid,oad_n)url='http://www.mafengwo.cn/hotel/captcha/check?ccode={0}&_ts={1}&_sn={2}'.format(code,str(t),sn)headers = {    'Cookie': cookie,    'Accept-Encoding': "gzip, deflate",    'Accept-Language': "zh-CN,zh;q=0.9",    'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",    'Accept': "application/json, text/javascript, */*; q=0.01",    'Referer': "http://www.mafengwo.cn/hotel/10035/",    'X-Requested-With': "XMLHttpRequest",    'Connection': "keep-alive",    'cache-control': "no-cache",    'Postman-Token': "620f7d41-d1de-4fe1-a69c-5a770227337a"    }
x=requests.get(url,headers=headers)print(x.text)

返回结果如下:

马蜂窝之酒店

再输入验证码后,就可以请求到包含酒店信息的网址了,这一部分同样也是将参数和_sn配对,如果配对成功就可以返回相应的信息。

还是打开之前的js文件,通过断点调试,得到进行md5加密的字符串。

通过修改里面的参数就可以获得任意网页的酒店信息了。

代码语言:javascript
复制
import hashlibimport requestsimport timedef par(t):    hl = hashlib.md5()    hl.update(t)    return hl.hexdigest()[2:12]page=1t=int(time.time()*1000)fromdata='2019-03-28'todata='2019-03-29'url = "http://www.mafengwo.cn/hotel/ajax.php"data='{"_ts":"'+str(t)+'","has_booking_rooms":"1","has_faved":"0","iAdultsNum":"2","iAreaId":"-1","iChildrenNum":"0","iDistance":"10000","iMddId":"10035","iPage":"'+str(page)+'","iPoiId":"","iPriceMax":"","iPriceMin":"","iRegionId":"-1","nLat":"0","nLng":"0","position_name":"","sAction":"getPoiList5","sCheckIn":"'+fromdata+'","sCheckOut":"'+todata+'","sChildrenAge":"","sKeyWord":"","sSortFlag":"DESC","sSortType":"comment","sTags":""}c9d6618dbc657b41a66eb0af952906f1'sn=par(data.encode('utf-8'))querystring = {"iMddId":"10035",               "iAreaId":"-1",               "iRegionId":"-1","iPoiId":"","position_name":"","nLat":"0","nLng":"0","iDistance":"10000",               "sCheckIn":fromdata,               "sCheckOut":todata,               "iAdultsNum":"2",               "iChildrenNum":"0",               "sChildrenAge":"",               "iPriceMin":"",               "iPriceMax":"",               "sTags":"","sSortType":"comment","sSortFlag":"DESC","has_booking_rooms":"1",               "has_faved":"0","sKeyWord":"","iPage":str(page),               "sAction":"getPoiList5","_ts":str(t),               "_sn":sn}
headers = {    # 'Cookie': "PHPSESSID=0ltaobjcharadcioh30akag7i7; mfw_uuid=5c90bbb0-8d5f-5df8-50bb-acf3b2f39a12; uva=s%3A78%3A%22a%3A3%3A%7Bs%3A2%3A%22lt%22%3Bi%3A1552989105%3Bs%3A10%3A%22last_refer%22%3Bs%3A6%3A%22direct%22%3Bs%3A5%3A%22rhost%22%3Bs%3A0%3A%22%22%3B%7D%22%3B; __mfwurd=a%3A3%3A%7Bs%3A6%3A%22f_time%22%3Bi%3A1552989105%3Bs%3A9%3A%22f_rdomain%22%3Bs%3A0%3A%22%22%3Bs%3A6%3A%22f_host%22%3Bs%3A3%3A%22www%22%3B%7D; __mfwuuid=5c90bbb0-8d5f-5df8-50bb-acf3b2f39a12; UM_distinctid=1699904eca797-0b6edef1fe2585-36637902-13c680-1699904eca868e; ad_widget_footer_20190314formal_2_other=1%2C1vuh0fz; oad_n=a%3A3%3A%7Bs%3A3%3A%22oid%22%3Bi%3A1029%3Bs%3A2%3A%22dm%22%3Bs%3A15%3A%22www.mafengwo.cn%22%3Bs%3A2%3A%22ft%22%3Bs%3A19%3A%222019-03-28+10%3A28%3A46%22%3B%7D; __mfwlv=1553740127; __mfwvn=7; CNZZDATA30065558=cnzz_eid%3D20394471-1553047971-%26ntime%3D1553739181; __mfwlt=1553744294",    'Accept-Encoding': "gzip, deflate",    'Accept-Language': "zh-CN,zh;q=0.9",    'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",    'Accept': "application/json, text/javascript, */*; q=0.01",    'Referer': "http://www.mafengwo.cn/hotel/10035/",    'X-Requested-With': "XMLHttpRequest",    'Connection': "keep-alive",    'cache-control': "no-cache",    'Postman-Token': "3b29182a-18b2-46a9-8a2a-d3cde4de70f9"    }response = requests.request("GET", url, headers=headers, params=querystring)print(response.text)

这样就可以获取数据啦。

关于马蜂窝就做到这里啦。有遗漏的地方欢迎补充

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-03-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python绿色通道 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
验证码
腾讯云新一代行为验证码(Captcha),基于十道安全栅栏, 为网页、App、小程序开发者打造立体、全面的人机验证。最大程度保护注册登录、活动秒杀、点赞发帖、数据保护等各大场景下业务安全的同时,提供更精细化的用户体验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档