前言:一覺睡醒,發現原有的搜狗微信爬蟲失效了,網上查找一翻發現10月29日搜狗微信改版了,無法通過搜索公眾號名字獲取對應文章了,不過通過搜索主題獲取對應文章還是可以的,問題不大,開搞!
目的:獲取搜狗微信中搜索主題返回的文章。
涉及反爬機制:cookie設置,js加密。
完整代碼已上傳本人github,僅供參考。如果對您有幫助,勞煩看客大人給個星星!
進入正題。
流程一:正常套路流程
打開搜狗微信,在搜索框輸入“咸蛋超人”,這里搜索出來的就是有關“咸蛋超人”主題的各個公眾號的文章列表:
按照正常的采集流程,此時按F12打開瀏覽器的開發者工具,利用選擇工具點擊列表中文章標題,查看源碼中列表中文章url的所在位置,再用xpath獲取文章url的值,也就是這個href的值,為避免混亂,我們稱之為“列表頁面的文章url”。
可以看到“列表頁面的文章url”需要拼接,一般這種情況需要在瀏覽器中正常訪問一下這篇文章,對比觀察跳轉后的url(我們稱之為“真實的文章url”),再缺頭補頭缺腳補腳即可。下面是兩個url的對比:
列表頁面的文章url: /link?url=dn9a_-gY295K0Rci_xozVXfdMkSQTLW6cwJThYulHEtVjXrGTiVgSwqn5HZrcjUNFzn4G2S0Yt3MduzuCU92ulqXa8Fplpd9CqUiLuEm9hLLvBiu5ziMS196rgHYb-GzQfleG917OgwN_VAAdAZHKryCeU9lIxtWTKnLsDcsuPIjLhLEK3tbGSa3_pkMzadQg75Zhmxb9YI0psZvVepKtN4hpzQgtGa2iOlKKLwV_oxooGE6sxg1qinKxTb5VwJUcLBM1RgkzAPRtmyIGw2VAg..&type=2&query=%E5%92%B8%E8%9B%8B%E8%B6%85%E4%BA%BA&k=92&h=z 真實的文章url: https://mp.weixin.qq.com/s?src=11×tamp=1573092595&ver=1959&signature=FjD709D-0vHSyVgQyXCS-TUAcnT0M9Gx6JljQEb6O55zpuyyDaTHqgkRCxNDtt5ZDifDRUUBOemzxcz71FMOmO88m6RWfR0r4fFBe0VefAsjFu0pl-M0frYOnXPF5JD8&new=1
這里很明顯兩個url的路徑不一致,應該是中間經過了一些調轉,python的requests庫是帶自動調轉功能,我們先把域名https://mp.weixin.qq.com補上試一下訪問
明顯這里做了反爬限制,那么這里開始,我們就需要抓包分析了。這里用到的工具是Firefox瀏覽器的開發者工具。抓包觀察的是從搜索結果頁面列表文章點擊跳轉到文章頁面的過程,這里點擊文章超鏈接會在新窗口打開,我們只需要在網頁源碼中把對應a標簽的target屬性改為空,就可以在一個窗口中觀察整個流程的數據包了。
流程二:抓包分析之跳轉實現
抓包分析:
通過抓包我們可以找到搜索結果頁面跳轉到文章頁面的過程,這里觀察發現,“列表頁面的文章url”返回的結果中就包含了“真實的文章url”的信息,這意味着我們只需要正確訪問到“列表頁面的文章url”,根據返回的數據就能拼接出“真實的文章url”並訪問了,這樣我們就實現從“列表頁面的文章url”到“真實的文章url”的跳轉了!
流程三:抓包分析之手動獲取的“列表頁面的文章url”無法訪問分析
此時我們的目標就從獲取“真實的文章url”轉變到正確的訪問“列表頁面的文章url”了,繼續分析抓包數據中的“列表頁面的文章url”信息:
抓包數據: url:https://weixin.sogou.com/link?url=dn9a_-gY295K0Rci_xozVXfdMkSQTLW6cwJThYulHEtVjXrGTiVgSwqn5HZrcjUNEnNekGBXt9LMduzuCU92ulqXa8Fplpd9CqUiLuEm9hLLvBiu5ziMS196rgHYb-GzQfleG917OgwN_VAAdAZHKryCeU9lIxtWTKnLsDcsuPIjLhLEK3tbGaBLLLEV3E0vo604DcwbvX2VNudQZNnBemevd34BJP94ZL5zUiA49LgzIjRlpGxccVxTTaLhHZKstaeqw41upSVAe0f8bRARvQ..&type=2&query=%E5%92%B8%E8%9B%8B%E8%B6%85%E4%BA%BA&k=60&h=U method:GET 請求參數:{"url":"dn9a_-gY295K0Rci_xozVXfdMkSQTLW6cwJThYulHEtVjXrGTiVgSwqn5HZrcjUNEnNekGBXt9LMduzuCU92ulqXa8Fplpd9CqUiLuEm9hLLvBiu5ziMS196rgHYb-GzQfleG917OgwN_VAAdAZHKryCeU9lIxtWTKnLsDcsuPIjLhLEK3tbGaBLLLEV3E0vo604DcwbvX2VNudQZNnBemevd34BJP94ZL5zUiA49LgzIjRlpGxccVxTTaLhHZKstaeqw41upSVAe0f8bRARvQ..","type":"2","query":"咸蛋超人","k":"60","h":"U"} headers: Host: weixin.sogou.com User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate, br Connection: keep-alive Referer: https://weixin.sogou.com/weixin?type=2&query=%E5%92%B8%E8%9B%8B%E8%B6%85%E4%BA%BA&ie=utf8&s_from=input&_sug_=n&_sug_type_=1&w=01015002&oq=&ri=1&sourceid=sugg&sut=750912&sst0=1573092594229&lkt=0%2C0%2C0&p=40040108 Cookie: 見下 Cookie:{"ABTEST":"4|1573094886|v1","IPLOC":"CN4401","JSESSIONID":"aaa3VBk4eXnIf8d4bdx4w","SNUID":"57A28ED20A0F9FB2BBE3E0180AF00D25","SUID":"5EAB87DB2613910A000000005DC385E6","SUV":"00F221C2DB87AB5E5DC385E7BC43F633"}
這里的重點有三個:
-
- 請求參數:對比我們獲取的“列表頁面的文章url”分析可以發現,這里多了兩個參數“k”、“h”,這是需要我們設法獲取的。
- headers:經過測試該網站對User-Agent敏感,一次訪問前后User-Agent需要一致。
- Cookie:Cookie中參數需要獲取才能正確訪問該url。這些參數分別是:ABTEST、IPLOC、JSESSIONID、SNUID、SUID、SUV。
3.1:獲取參數“k”、“h”
按照經驗,從一個url轉變成另一個url有兩種情況:跳轉和javascript字符串處理。經過多次抓包分析發現,搜索結果頁面點擊文章超鏈接到我們現在的目標url並沒有存在跳轉情況,抓包數據中的“列表頁面的文章url”和我們獲取的“列表頁面的文章url”可以判定為同一個url,所以猜測為javascript字符串處理。經過一番搜尋,發現搜索結果頁面的源碼中有一段非常可疑的代碼:
<script> (function(){$("a").on("mousedown click contextmenu",function(){var b=Math.floor(100*Math.random())+1,a=this.href.indexOf("url="),c=this.href.indexOf("&k=");-1!==a&&-1===c&&(a=this.href.substr(a+4+parseInt("21")+b,1),this.href+="&k="+b+"&h="+a)})})(); </script>
這其中最重要的代碼就是:this.href+="&k="+b+"&h="+a,這代碼就是在點擊事件發生時給a標簽href屬性的內容添加"&k="、"&h=",正是用這段代碼對該url的參數進行js加密和添加的。我們只需要把這段代碼用python實現就可以解決這個問題了,下面是實現python實現代碼:
def get_k_h(url):
b = int(random.random() * 100) + 1 a = url.find("url=") url = url + "&k=" + str(b) + "&h=" + url[a + 4 + 21 + b: a + 4 + 21 + b + 1]
reuturn url
3.2:獲取Cookie的參數
觀察抓包數據可以發現,當我們一開始訪問時並沒有帶任何cookie,但經過一系列請求,到我們的目標請求時候,瀏覽器已經通過前面請求的返回數據包的Set-Cookie屬性把Cookie構造出來了,而我們要做的就是在Cookie構造從無到有這個過程中找到所有ResponseHeaders中帶SetCookie屬性的而且參數是我們需要的參數的請求,並模擬訪問一遍,就能得到所有參數並構建出我們需要的Cookie了。
例如搜狗微信搜索接口的請求的ResponseHeaders就有5個Set-Cookie字段,其中ABTEST、SNUID、IPLOC、SUID都是我們最終構造Cookie所需的參數(和最后的Cookie值對比可以發現,這里的SUID值還不是我們最終需要的,要在后面的數據包中繼續發掘)。
經過分析,經過四個請求獲取到的ResponseHeaders后我們就能正確構建Cookie了:
1. 得到ABTEST、SNUID、IPLOC、SUID:
https://weixin.sogou.com/weixin?type=2&query=%E5%92%B8%E8%9B%8B%E8%B6%85%E4%BA%BA&ie=utf8&s_from=input&_sug_=n&_sug_type_=1&w=01015002&oq=&ri=1&sourceid=sugg&sut=750912&sst0=1573092594229&lkt=0%2C0%2C0&p=40040108
2. 需要IPLOC、SNUID,得到SUID:
https://www.sogou.com/sug/css/m3.min.v.7.css
3. 需要ABTEST、IPLOC、SNUID、SUID,得到JSESSIONID:
https://weixin.sogou.com/websearch/wexinurlenc_sogou_profile.jsp
4. 需要IPLOC、SNUID、SUID,得到SUV
https://pb.sogou.com/pv.gif
這四個請求都能根據前面請求獲取到的Cookie參數來構造自己需要的Cookie去正確訪問。值得注意的是最后一個請求,除了需要正確拼接Cookie外,還需要獲取正確的請求參數才能正常訪問:
這種找參數的活可以利用瀏覽器的全局搜索功能,一番搜尋后,就會發現在搜索結果頁面的源代碼中已經返回了這里所需的所有參數,用正則把這些參數解析出來即可:
那么根據這些解析出來的參數和前面三個請求得到的Cookie參數就能正確訪問第四個請求並得到所需的所有Cookie參數啦!
流程四:構造正確的請求信息
此時,我們已經分析出所有正確模擬請求的流程了,梳理一下:
- 獲取“k”、“h”參數,傳入搜索結果頁面得到的“列表頁面的文章ur”,調用get_k_h()即可。
- 獲取所需Cookie參數,構造正確的Cookie,按照流程三給出的4個url,分別構造請求獲取ResponseHeaders中的SetCookie即可。
- 構造正確的請求訪問“列表頁面的文章url”。
- 根據3中請求返回的數據,拼接出“真實的文章url”,也就是流程二。
- 請求“真實的文章url”,得到真正的文章頁面數據。
至此,所有分析結束,可以愉快的碼代碼啦!
結語:此次采集涉及到的反爬技術是Cookie構造和簡答的js加密,難度不大,最重要的是耐心和細心。此外提醒各位看客大人遵循爬蟲道德,不要對他人網站造成傷害,peace!