python爬蟲js加密篇—搜狗微信公號文章的爬取

今天這篇文章主要介紹的是關於微信公衆號文章的爬取,其中裏面主要涉及的反爬機制就是 js加密與cookies的設置


微信公衆號的上一個版本中的反爬機制中並沒有涉及到js加密,僅通過監控用戶ip,單個ip訪問太頻繁會面臨被封的風險;在新的版本中加入了js加密反爬機制,接下來我們來逐步分析一下文章爬取過程

打開搜狗頁面搜狗微信頁面,在輸入框中輸入任意關鍵詞例如火車隧道起火,搜出來的都是涉及關鍵詞的公號文章列表

image


這裏按照平常套路,直接利用開發者工具的選擇工具,查看源碼中列表中每篇文章的url,就是下面這個 href屬性 標籤,
image

看到這個url,按照正常思路的話,就是直接做url拼接:搜狗主域名 + href 就是微信主要內容的url,形式如下

https://weixin.sogou.com/link?url=dn9a_-gY295K0Rci_xozVXfdMkSQTLW6cwJThYulHEtVjXrGTiVgS_yBZajb90fWf-LwgFP7QmnFtbELADqFzFqXa8Fplpd9nrYbnf-BG6fJQmhdTDKRUQC_zVYwjAHQRnKwtfQUOD-aNBz2bhtCuShQywQb837B12cBkYFsYkKXir7Y9WqlRBcZIrhUAYmFlBSVIg7YGFbBdu4rXklGlRslEFpw0lTmIX8pHfpQ9x6clCHaA92qoA9YOaIV2yOyrE-focNFXq7wdVqCwyPdzA..&type=2&query=%E7%81%AB%E8%BD%A6%E9%9A%A7%E9%81%93%E8%B5%B7%E7%81%AB

但是直接點這個鏈接返回的是402頁面,需要輸入驗證碼進行驗證,而且驗證碼通過後依然進不去;很明顯這個url並不是文章的訪問入口


image

經過測試,這篇文章的真實url是下面這種形式(直接通過點擊頁面標籤打開即可):

https://mp.weixin.qq.com/s?src=11&timestamp=1567073292&ver=1820&signature=z2h7E*HznopGFidmtUA4PmXgi3ioRqV7XiYIqn9asMT3RCMKss6Y2nPUh7RG63nrwmRii77cL9LyDNJIVp1qpo5LHvQ8s754Q9HtCgbp5EPUP9HjosY7HWDwze6A2Qi7&new=1

是不是很很意外;這裏開始就需要轉變思路:不管怎樣最好先抓一下包,這裏我利用的工具是Fidder,關於Fidder如何使用,可以參照這篇文章:Fidder工具的使用!

先從搜索頁面的文章列表中進入文章的詳情頁,我們需要通過Fidder來監控一下文章的跳轉情況:

image


看到沒,驚奇地發現有個 /link?url 開頭的url跳轉成功了,深入一下,我們再看一下這個鏈接返回的是什麼,點一下response部分的TextView;

在這裏插入圖片描述
返回的text文本是一串字符串組成的,即使不懂javascript,但裏面大概意思就是構造一個url,格式與前面那個真實的url有一些相似呢,經測試之後發現,返回的這個url就是獲取文章內容的真實url

把這個訪問成功的並且以link?url開頭的url完整複製下來,與源碼中的那個 link?url 放在一起,發現這個訪問成功的url中多了兩個參數一個是k一個是h

# 訪問成功的:https://weixin.sogou.com/link?url=dn9a_-gY295K0Rci_xozVXfdMkSQTLW6cwJThYulHEtVjXrGTiVgS_yBZajb90fWf-LwgFP7QmnFtbELADqFzFqXa8Fplpd9nrYbnf-BG6fJQmhdTDKRUQC_zVYwjAHQRnKwtfQUOD-aNBz2bhtCuShQywQb837B12cBkYFsYkKXir7Y9WqlRBcZIrhUAYmFlBSVIg7YGFbBdu4rXklGlRslEFpw0lTmIX8pHfpQ9x6clCHaA92qoA9YOaIV2yOyrE-focNFXq7wdVqCwyPdzA..&type=2&query=%E7%81%AB%E8%BD%A6%E9%9A%A7%E9%81%93%E8%B5%B7%E7%81%AB&k=80&h=f 
# 訪問失敗的:https://weixin.sogou.com/link?url=dn9a_-gY295K0Rci_xozVXfdMkSQTLW6cwJThYulHEtVjXrGTiVgS_yBZajb90fWf-LwgFP7QmnFtbELADqFzFqXa8Fplpd9nrYbnf-BG6fJQmhdTDKRUQC_zVYwjAHQRnKwtfQUOD-aNBz2bhtCuShQywQb837B12cBkYFsYkKXir7Y9WqlRBcZIrhUAYmFlBSVIg7YGFbBdu4rXklGlRslEFpw0lTmIX8pHfpQ9x6clCHaA92qoA9YOaIV2yOyrE-focNFXq7wdVqCwyPdzA..&type=2&query=%E7%81%AB%E8%BD%A6%E9%9A%A7%E9%81%93%E8%B5%B7%E7%81%AB

現在基本爬取核心思路已經知道了,主要就是破解這兩個參數k和h,拼接成’真’的url( 以/cl.gif開頭的 ),然後獲取真url;

關於這兩個參數的破解就是涉及到了js加密,需要進行調試,不懂的可以參考這篇文章:Chrome DevTools 中調試 JavaScript 入門;

第一步,回到源碼中 link?url 位置的地方,因爲後面兩個參數的增加是由於我們觸發了這個假的url,所以這裏需要對假的url進行監聽:
開發者工具[Elements] -> 右上角處的[Event Listeners] -> [click] -> 你需要監控的元素標籤

image

第二步,按流程瀏覽完上面所有過程時下面會有個js文件,點進去,並對js代碼進行格式化,發現參數k與h的構造方法:


image


其實還有一種參數定位的方法,在Google開發者選項中利用全局搜索**[Search]就能快速定位,但是並不適用於這裏,因爲這裏我們定位的參數都是單個元素,定位的準確度特別低

定位之後,參數
kh**的定義非常清楚,沒有過多函數嵌套,就是在一個簡單的函數中,一個是生成一個隨機數字,另一個在這個href標籤的鏈接中獲取其中的某一個字符,這裏我們可以直python把這個功能實現:

 url_list11  = pq(res.text)('.news-list li').items()
    for i in url_list11:
        url_list12 = pq(i('.img-box a').attr('href'))
        url_list12 =str(url_list12).replace('<p>','').replace('</p>','').replace('amp;','')
        print(url_list12)
        b = int(random.random() * 100) + 1
        a = url_list12.find("url=")
        result_link = url_list12 + "&k=" + str(b) + "&h=" + url_list12[a + 4 + 21 + b: a + 4 + 21 + b + 1]
        a_url ="https://weixin.sogou.com" +result_link

好了,‘真’url也能夠構造成功了,通過訪問‘真’url來獲取 真url(訪問時記得加上headers),然後再獲取我們需要的信息;然而結果卻是下面這樣的:


image


經測試發現,原因是由於Cookie中最爲核心的兩個參數SUV和SUNID,而這兩個參數在不斷地發生改變

其中SUNID有固定得訪問次數/時間限制,超過了限制直接變爲無效,並且當訪問網頁請求失敗後,SUNID與SUV需要更換才能再次正常訪問;

SUV參數是在 ‘真’url 過度到 真url 中某個網頁中Response裏的Set-Cookie中生成的,也就是下面這個網頁:

image

需要我們請求這個鏈接,通過這個鏈接返回的Cookie,我們拿到這個Cookie放入請求頭裏面,再訪問拼接好的 ** ‘真’ url**

最後就能獲取到真url最後請求這個鏈接,解析出我們想要的數據( 注意用請求頭的時候最好不要加Cookies,否則會導致訪問失敗 )
當解決以上所有問題了,這裏再測試一下,已經能夠成功地拿到我們想要的數據:


image
上面是部分板塊代碼,想要獲取全部源碼,關注微信公衆號:Z先生點記 ;後臺回覆關鍵詞: 搜狗 即可。

def get_suva(sunid):
    '''
    根據sunid來獲取suv參數;並添加到cookie衆
    :param a: sunid
    :return: 
    '''
    b_data['snuid'] = sunid.split('=')[-1]
    b_data['uuid'] = uuid.uuid1()
    b_data['uigs_t'] = str(int(round(time.time() * 1000)))
    url_link = 'https://pb.sogou.com/pv.gif?' + urlencode(b_data)
    res = requests.get(url_link)
    cookie_s = res.headers['Set-Cookie'].split(',')
    cookie_list_s = []
    for i in cookie_s:
        for j in i.split(','):
            if 'SUV' in j:
                cookie_list_s.append(j)
            else:
                continue
    print(cookie_list_s[0].split(';')[0])
    headers['Cookie'] = cookie_list_s[0].split(';')[0]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章