捅马蜂窝啦!!!

2019-04-25 13:52:14 浏览数 (1)

马蜂窝之旅游问答

上图为马蜂窝的旅游问答页(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":"{"poi_id":"87950","page":{},"just_comment":1}".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[]":"all","reduce[]":"all","tag_group[9365][]":"all","tag_group[9521][]":"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:78:"a:3:{s:2:"lt";i:1552989105;s:10:"last_refer";s:6:"direct";s:5:"rhost";s:0:"";}";; __mfwurd=a:3:{s:6:"f_time";i:1552989105;s:9:"f_rdomain";s:0:"";s:6:"f_host";s:3:"www";}; __mfwuuid=5c90bbb0-8d5f-5df8-50bb-acf3b2f39a12; UM_distinctid=1699904eca797-0b6edef1fe2585-36637902-13c680-1699904eca868e; ad_widget_footer_20190314formal_2_other=1,1vuh0fz; __mfwothchid=referrer|www.mafengwo.cn; __mfwlv=1553501567; __mfwvn=6; CNZZDATA30065558=cnzz_eid=20394471-1553047971-&ntime=1553506977; __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:78:"a:3:{s:2:"lt";i:1552989105;s:10:"last_refer";s:6:"direct";s:5:"rhost";s:0:"";}";; __mfwurd=a:3:{s:6:"f_time";i:1552989105;s:9:"f_rdomain";s:0:"";s:6:"f_host";s:3:"www";}; __mfwuuid=5c90bbb0-8d5f-5df8-50bb-acf3b2f39a12; UM_distinctid=1699904eca797-0b6edef1fe2585-36637902-13c680-1699904eca868e; ad_widget_footer_20190314formal_2_other=1,1vuh0fz; oad_n=a:3:{s:3:"oid";i:1029;s:2:"dm";s:15:"www.mafengwo.cn";s:2:"ft";s:19:"2019-03-28 10:28:46";}; __mfwlv=1553740127; __mfwvn=7; CNZZDATA30065558=cnzz_eid=20394471-1553047971-&ntime=1553739181; __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)

这样就可以获取数据啦。

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

0 人点赞