大話爬蟲的實踐技巧


爬蟲與反爬蟲間的對決

圖1-意淫爬蟲與反爬蟲間的對決

數據的重要性

現在已然是大數據時代,數據正在驅動着業務開發,驅動着運營手段,有了數據的支撐能夠對用戶進行用戶畫像,個性化定製,數據能夠指明方案設計和決策優化方向,因此互聯網產品的開發都是離不開對數據的收集和分析,數據收集的一種是方式是經過上報API進行自身平臺用戶交互狀況的捕獲,還有一種手段是經過開發爬蟲程序,爬取競品平臺的數據,後面就重點說下爬蟲的應用場景和實踐中會遇到的問題和反反爬蟲的一些套路與技巧。css


應用場景

  • 互聯網平臺,偏向銷售公司,客戶信息的爬取html

    • 客戶信息的爬取能夠釋放銷售人員尋找客戶資源的時間,提升銷售對市場開發的效率
    • 爬取相關平臺上的客戶信息,上報到CRM管理系統,提供給銷售人員進行開發
  • 資訊爬取並應用到平臺業務中前端

    • 常常瀏覽資訊的時候會發現其實不少平臺的熱門資訊內容都很類似,尊重版權的平臺,會標明來源出處
    • 爬取資訊信息,應用到資訊業務中,能夠減輕資訊內容編輯人員的壓力,若是不須要創造本身的內容,也可所有託管給程序AI運營
  • 競品公司重要數據挖掘分析與應用python

    • 競品平臺重要業務數據,如:汽車X家的車型信息,X哪兒的酒店信息,返X網的商品信息,... ...
    • 爬取競品重要數據,對數據進行篩選和處理,而後投入業務中展現,增長這塊業務數據量,減輕這塊資源的運營編輯的壓力
  • ... ...

爬蟲開發

  • python開發爬蟲(推薦)git

    • 入門也比較簡單,代碼短小精幹,各類便於爬蟲開發的模塊和框架
  • 其餘語言程序員

    • 不少語言也均可以開發爬蟲,可是均都不是很全面,根據實際技術棧和開發場景去使用,語言只是工具,思路纔是通用的

爬蟲必備技巧

作爬蟲開發,須要對WEB這塊有相對全面深刻的理解,這樣後面遇到反爬蟲才能駕輕就熟,見招拆招
  • 瞭解HTMLgithub

    • 會使用HTML標籤構造頁面,知道如何解析出DOM裏標籤,提取想要的數據內容
  • 瞭解CSSweb

    • 瞭解CSS,會解析出樣式裏的數據內容
  • 瞭解JS數據庫

    • 基本JS語法,能寫能讀懂,並瞭解JS庫:Jquery,Vue 等,能夠對使用開發者工具調試JS
  • 瞭解JSON瀏覽器

    • 瞭解JSON數據,會序列化和反序列化數據,經過解析JSON對象獲取數據內容
  • 瞭解HTTP/HTTPS

    • 可以分析請求信息和響應信息,能夠經過代碼構造請求
  • 會正則解析

    • 經過正則匹配出符合規則的字符串,提取想要的數據內容
  • 會數據庫操做

    • 經過數據庫操做對爬取數據進行存儲,如:MYSQL語法
  • 會使用抓包工具

    • 瀏覽器F12開發者調試工具(推薦:谷歌),Network(網絡)欄目能夠獲取抓包信息
    • 工具:Charles,Fiddler (可抓包HTTPS,抓包APP)
    • 經過抓包工具能夠過濾出數據接口或者地址,而且分析請求信息和響應信息,定位數據所在的字段或者HTML標籤
  • 會使用開發者工具

    • 瀏覽器F12開啓開發者工具
    • 須要會使用開發者工具調試HTML,CSS,JS
  • 會模擬請求

    • 工具:Charles,Fiddler,Postman
    • 經過模擬請求,分析出請求須要那些必要的信息,如:參數,COOKIE,請求頭,懂得怎麼模擬請求就知道編碼的時候如何去構造
  • 能定位數據

    • 數據在API中:前端/原生APP請求數據API,API返回數據大部分是JSON格式,而後渲染展現
    • 數據在HTML中:查看頁面HTML源代碼,若是源代碼裏有想要獲取的數據,就說明在服務端已經綁定好數據在HTML裏
    • 數據在JS代碼中:查看頁面HTML源代碼,若是獲取數據不在HTML裏,又沒有請求數據API,能夠看下數據是否是綁定到JS變量裏
  • 會部署

    • 能夠部署到Windows或者Linux服務器,使用工具進行爬蟲進程監控,而後進行定時輪訓爬取

反爬蟲對抗技巧

反爬蟲能夠分爲 服務端限制前端限制
服務端限制:服務器端行請求限制,防止爬蟲進行數據請求
前端限制:前端經過CSS和HTML標籤進行干擾混淆關鍵數據,防止爬蟲輕易獲取數據

設置請求頭(服務端限制

  • Referer
  • User-Agent
  • ... ...

簽名規則(服務端限制

  • 若是是JS發起的請求,簽名規則能夠在JS函數中找到,而後再根據規則去構造簽名
  • 若是是APP發起的請求,多是前端調用原生封裝的方法,或者原生髮起的,這個就比較無解,須要反編譯APP包,也不必定能成功

延遲,或者隨機延遲(服務端限制

  • 若是請求被限制,建議能夠試試請求延遲,具體延遲xxx毫秒/x秒,根據實際狀況設定合適的時間

代理IP(服務端限制

  • 若是延遲請求仍是被限制,或者須要延遲很長時間纔不會被限制,那就能夠考慮使用代理IP,根據實際場景與限制的規律去運用,通常只要被限制的時候就切換請求的代理IP,這樣就基本能夠繞過限制
  • 目前有不少收費的代理IP服務平臺,有各類服務方式,具體能夠搜索瞭解下,費用通常都在能夠接受的範圍

登陸限制(服務端限制

  • 請求帶上登陸用戶的COOKIE信息
  • 若是登陸用戶COOKIE信息會在固定週期內失效,那就要找到登陸接口,模擬登陸,存儲COOKIE,而後再發起數據請求,COOKIE失效後從新這個步驟

驗證碼限制(服務端限制

  • 簡單驗證碼,對圖片裏的字母或者數字進行識別讀取,使用識圖的模塊包能夠實現
  • 複雜驗證碼,沒法經過識圖識別,能夠考慮使用第三方收費服務

CSS/HTML混淆干擾限制(前端限制

前端經過CSS或者HTML標籤進行干擾混淆關鍵數據,破解須要抽樣分析,找到規則,而後替換成正確的數據

1 . font-face,自定義字體干擾

如列子:汽車X家論帖子貓X電影電影評分

<!--css-->
<!--找到://k3.autoimg.cn/g13/M05/D3/23/wKjByloAOg6AXB-hAADOwImCtp047..ttf--> 
<style>
    @font-face {font-family: 'myfont';src: url('//k2.autoimg.cn/g13/M08/D5/DD/wKgH41oAOg6AMyIvAADPhhJcHCg43..eot');src: url('//k3.autoimg.cn/g13/M08/D5/DD/wKgH41oAOg6AMyIvAADPhhJcHCg43..eot?#iefix') format('embedded-opentype'),url('//k3.autoimg.cn/g13/M05/D3/23/wKjByloAOg6AXB-hAADOwImCtp047..ttf') format('woff');}
</style>

<!--html-->
<!--會員招募中-->
<div>&nbsp;Mercedes&nbsp;C+&nbsp;會員招募<span style='font-family: myfont;'>&#xf159;</span></div>

<!--
    從html中獲取【html中文編碼】=&#xf159
    而後解析ttf文件獲得【ttf中文編碼】列表
    匹配發現【ttf中文編碼】=uniF159能夠與【html中文編碼】=&#xf159匹配,在第7個,第7箇中文就是"中"
    (抽樣分析會發現ttf中中文位置是固定的,中文編碼是動態變化的,因此只要映射出【ttf中文編碼】索引就能夠知道中文字符了)
-->

破解思路:
找到ttf字體文件地址,而後下載下來,使用font解析模塊包對ttf文件進行解析,能夠解析出一個字體編碼的集合,與dom裏的文字編碼進行映射,而後根據編碼在ttf裏的序號進行映射出中文

可使用FontForge/FontCreator工具打開ttf文件進行分析

2 . 僞元素隱藏式

經過僞元素來顯示重要數據內容
如例子:汽車X家

<!--css-->
<style>
.hs_kw60_configod::before {
    content: "一汽";
}
.hs_kw23_configod::before {
    content: "大衆";
}
.hs_kw26_configod::before {
    content: "奧迪";
}
</style>

<!--html-->
<div>
    <span class="hs_kw60_configod"></span>
    -
    <span class="hs_kw23_configod"></span>
    <span class="hs_kw26_configod"></span>
</div>

破解思路:
找到樣式文件,而後根據HTML標籤裏class名稱,匹配出CSS裏對應class中content的內容進行替換


3 . backgroud-image

經過背景圖片的position位置偏移量,顯示數字/符號,如:價格,評分等
根據backgroud-postion值和圖片數字進行映射


4 . html標籤干擾

經過在重要數據的標籤里加入一些有的沒的隱藏內容的標籤,干擾數據的獲取
如例子:xxIP代理平臺

<!--html-->
<td class="ip">
    <p style="display:none;">2</p>
    <span>2</span>
    <span style="display:inline-block;"></span>
    <div style="display: inline-block;">02</div>
    <p style="display:none;">.1</p>
    <span>.1</span>
    <div style="display:inline-block;"></div>
    <span style="display:inline-block;"></span>
    <div style="display:inline-block;">09</div>
    <span style="display: inline-block;">.</span>
    <span style="display:inline-block;">23</span>
    <p style="display:none;">7</p>
    <span>7</span>
    <p style="display:none;"></p>
    <span></span>
    <span style="display: inline-block;">.</span>
    <div style="display: inline-block;"></div>
    <p style="display:none;">3</p>
    <span>3</span>
    <div style="display: inline-block;">5</div>:
    <span class="port GEA">80</span>
</td>
<!--js-->
<script>
    $(".ip:eq(0)>*:hidden").remove()
    $(".ip:eq(0)").text()
</script>
<!--
    輸出:202.109.237.35:80
    經過移除干擾標籤裏有display:none隱藏標籤,而後再獲取text就不會有干擾的內容了
-->

破解思路:
過濾掉干擾混淆的HTML標籤,或者只讀取有效數據的HTML標籤的內容

看穿一切

... ... (反爬蟲腦洞有多大,反反爬蟲拆招思路就有多淫蕩)

防止投毒

  • 有些平臺發現爬蟲後並不會進行限制封殺,而是給爬蟲提供誤導的數據,影響競品公司進行錯誤的決策,這就是投毒
  • 爲了防止被投毒,須要對數據進行抽樣校驗

總結

別怪我沒提醒你

  1. 目前大部分中小平臺對防護爬蟲的意識還比較薄弱,促使了爬蟲的盛行,經過爬蟲能夠用比較小的代價,獲取更大的利益
  2. 競品數據的挖掘分析與應用對於業務增加有着舉足輕重的做用,爬蟲開發對於互聯網產品公司的來講是個必不可少的技術
  3. 當前並無一種能夠徹底避免爬蟲的技術,因此添加反爬蟲策略只是增長了必定的難度門檻,只要拆招技術夠硬仍是能夠被突破翻越
  4. 反爬蟲和反反爬蟲是技術之間的較量,這場沒有硝煙的戰爭永不停息。(程序員何須爲難程序員)

供參考代碼

font解析 C#和Python實現
  • C#
/// 須要引入PresentationCore.dll
private void Test() {
            string path = @"F:\font.ttf";
            //讀取字體文件             
            PrivateFontCollection pfc = new PrivateFontCollection();
            pfc.AddFontFile(path);
            //實例化字體
            Font f = new Font(pfc.Families[0], 16);
            //設置字體
            txt_mw.Font = f;

            //遍歷輸出
            var families = Fonts.GetFontFamilies(path);
            foreach (System.Windows.Media.FontFamily family in families) {
                var typefaces = family.GetTypefaces();
                foreach (Typeface typeface in typefaces) {
                    GlyphTypeface glyph;
                    typeface.TryGetGlyphTypeface(out glyph);
                    IDictionary<int, ushort> characterMap = glyph.CharacterToGlyphMap;
                    var datas = characterMap.OrderBy(d => d.Value).ToList();
                    foreach (KeyValuePair<int, ushort> kvp in datas) {
                        var str = $"[{kvp.Value}][{kvp.Key}][{(char)kvp.Key}]\r\n";
                        txt_mw.AppendText(str);
                    }
                }
            }

        }
  • python
# pip install TTFont
from fontTools.ttLib import TTFont
from fontTools.merge import *
me = Merger()
font = TTFont('./font.ttf')
cmaps = font.getBestCmap()
orders = font.getGlyphOrder()
# font.saveXML('F:/1.xml')
print cmaps
print orders

自我推薦


供參考資料


閱讀原文

相關文章
相關標籤/搜索