1. 程式人生 > >python攜程爬蟲之逆向混淆js

python攜程爬蟲之逆向混淆js

前言

那些年攜程工程師在程式碼裡下的毒-反爬與反反爬的奇技淫巧 知乎上面的專欄,寫出了逆向找到攜程的Eleven引數來偽裝瀏覽器傳送ajax,獲取攜程的酒店房型列表。然而文章並沒有給出全部的思路,我們獲取到的頁面內容內容是醬紫的:

在這裡插入圖片描述

在這裡插入圖片描述 所以沒辦法,只能自己擼出來,看看到底是怎麼加密的。

DEBUG

首先還是檢視ajax請求網址時 http://hotels.ctrip.com/Domestic/tool/AjaxHote1RoomListForDetai1.aspx?psid=&MasterHotelID=441351&hotel=441351&EDM=F&roomId=&IncludeRoom=&city=2&showspothotel=T&supplier=&IsDecoupleSpotHotelAndGroup=F&contrast=0&brand=0&startDate=2017-08-28&depDate=2017-08-29&IsFlash=F&RequestTravelMoney=F&hsids=&IsJustConfirm=&contyped=0&priceInfo=-1&equip=&filter=&productcode=&couponList=&abForHuaZhu=&defaultLoad=T&TmFromList=F&eleven=c4350e460862b69d9d76724e1325a0a54ef23c2e0648636c855a329418018a85&callback=CASuBCgrghIfIUqemNE&_=1503884369495

的程式碼, 尋找他的呼叫棧。 在這裡插入圖片描述

$.ajax(o, {
    onsuccess: function(e) {
        window[n](e.responseText)//
    },
    onerror: function() {
        window[n] = void 0,
        r()
    }
}

而執行函式的時候傳入的引數就是我們剛剛ajax得到的的json內容。我們打上斷點後可以發現e.responseText為訪問頁面得到的json轉化而成字串。 在這裡插入圖片描述window[n]方法就在上方

 window[n] = function(e) {
      window[
n] = void 0; var i = ["T", "F", "e", "s", "M", "a", "g", "r", "o", "B", "u", "l", "y", "m", "f", "t"]; e = $.parseJSON(e), null == e ? r() : (hotelDomesticConfig.cas.Pretty && e["0|2|3|15|4|2|3|3|5|6|2|1|7|8|13|9|10|15|15|2|7|14|11|12".split("|").map(function(e) { return
i[e] }).join("")].slice(-9999).indexOf(" ") !== -1 ? e.html = "" : !l && hotelDomesticConfig.cas.decrypt && (e.html = t(e.ComplexHtml, e.ASYS, e.html)), s(e)), $('script[src="' + o + '"]').remove() }

我們在return i[e]$('script[src="' + o + '"]').remove()處打上斷點。執行的時候直接跳過了return i[e],我們再看一下各變數的值。 在這裡插入圖片描述

e 原本為傳入的e.responseText的值,既字串,如今變成了一個物件,瀏覽一下他的屬性。發現有一個html的屬性,內容如下:

<div class="htl_room_table J_roomTable"><table border="0" cellspacing="0" cellpadding="0" summary="詳情頁酒店房型列表" id="J_RoomListTbl"><tr><th class="col1" style="padding-left:10px;">房型</th><th class="col2"></th><th class="col3">床型</th><th class="col5">寬頻</th><th class="col_person">入住人數</th></i><p>沒有符合條件的房型,您可以減少當前篩選項或<a id="J_ShowAllRoomList" href="javascript:void(0);">檢視全部房型</a></p></td></script>

由於太長我沒有吧全部程式碼放出來。可以看出,這裡就是我們想要的結果。 於是我排查了window[n]裡的每一個句子,找到了(e.html = t(e.ComplexHtml, e.ASYS, e.html),其中e.ComplexHtml以及e.ASYS就是ajax得到的兩個奇形怪狀的欄位, 跳轉到t函式。

 function t(e, t, o) {
     var i = "";
     if ("function" != typeof NODEJS)
         return "";
     if ("undefined" == typeof e)
         return "";
     if (!e)
         return "";
     try {
         i = NODEJS(e, t)
     } catch (n) {
         i = ""
     }
     return i
 }

return i 的時候,i已經是html的字串了。所以我們可以判斷就是在方法名為NODEJS之中完成的解密。

NODEJS = function(n, t) {
    var r, o, e = "1", i = void 0 == e[0], c = i ? [] : "";
    for (r = 0; r < n.length; r++)
        o = t.charAt(n.charAt(r).charCodeAt(0) - 21760).charAt(0),
        i ? c.push(o) : c += o;
    return c = i ? c.join("") : c
}

把上面的函式e.ComplexHtmle.ASYS丟到node中執行,結果出來的就是html的字串。 撒花完結 ##總結 寫了個python版本的,丟:

def decrypt(n, t):
    c = ""
    for i in n:
        try:
            o = t[ord(i) - 21760]
        except:
            o = ""
        c = c + o
    return c