搜狗微信採集 —— python爬蟲系列一

  前言:一覺睡醒,發現原有的搜狗微信爬蟲失效了,網上查找一翻發現10月29日搜狗微信改版了,沒法經過搜索公衆號名字獲取對應文章了,不過經過搜索主題獲取對應文章仍是能夠的,問題不大,開搞!javascript

  目的:獲取搜狗微信中搜索主題返回的文章。css

  涉及反爬機制:cookie設置,js加密。html

  完整代碼已上傳本人github(今晚放出),僅供參考。若是對您有幫助,勞煩看客大人給個星星!java

  進入正題。python

 

流程一:正常套路流程

  打開搜狗微信,在搜索框輸入「鹹蛋超人」,這裏搜索出來的就是有關「鹹蛋超人」主題的各個公衆號的文章列表:git

 

 

   按照正常的採集流程,此時按F12打開瀏覽器的開發者工具,利用選擇工具點擊列表中文章標題,查看源碼中列表中文章url的所在位置,再用xpath獲取文章url的值,也就是這個href的值,爲避免混亂,咱們稱之爲「列表頁面的文章url」。github

 

 

  能夠看到「列表頁面的文章url」須要拼接,通常這種狀況須要在瀏覽器中正常訪問一下這篇文章,對比觀察跳轉後的url(咱們稱之爲「真實的文章url」),再缺頭補頭缺腳補腳便可。下面是兩個url的對比:web

 

列表頁面的文章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&timestamp=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"}

   

  這裏的重點有三個:

    1. 請求參數:對比咱們獲取的「列表頁面的文章url」分析能夠發現,這裏多了兩個參數「k」、「h」,這是須要咱們設法獲取的。
    2. headers:通過測試該網站對User-Agent敏感,一次訪問先後User-Agent須要一致。
    3. 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參數啦!

 

流程四:構造正確的請求信息

  此時,咱們已經分析出全部正確模擬請求的流程了,梳理一下:

  1. 獲取「k」、「h」參數,傳入搜索結果頁面獲得的「列表頁面的文章ur」,調用get_k_h()便可。
  2. 獲取所需Cookie參數,構造正確的Cookie,按照流程三給出的4個url,分別構造請求獲取ResponseHeaders中的SetCookie便可。
  3. 構造正確的請求訪問「列表頁面的文章url」。
  4. 根據3中請求返回的數據,拼接出「真實的文章url」,也就是流程二。
  5. 請求「真實的文章url」,獲得真正的文章頁面數據。

  至此,全部分析結束,能夠愉快的碼代碼啦!

  

結語:這次採集涉及到的反爬技術是Cookie構造和簡答的js加密,難度不大,最重要的是耐心和細心。此外提醒各位看客大人遵循爬蟲道德,不要對他人網站形成傷害,peace!

相關文章
相關標籤/搜索