圖片
  

什麼是爬蟲?

網路爬蟲也叫網路蜘蛛,如果把網際網路比喻成一個蜘蛛網,那麼蜘蛛就是在網上爬來爬去的蜘蛛,爬蟲程式通過請求url地址,根據響應的內容進行解析採集資料,
比如:如果響應內容是html,分析dom結構,進行dom解析、或者正則匹配,如果響應內容是xml/json資料,就可以轉資料物件,然後對資料進行解析。


有什麼作用?

通過有效的爬蟲手段批量採集資料,可以降低人工成本,提高有效資料量,給予運營/銷售的資料支撐,加快產品發展。


業界的情況

目前網際網路產品競爭激烈,業界大部分都會使用爬蟲技術對競品產品的資料進行挖掘、採集、大資料分析,這是必備手段,並且很多公司都設立了爬蟲工程師的崗位


合法性

爬蟲是利用程式進行批量爬取網頁上的公開資訊,也就是前端顯示的資料資訊。因為資訊是完全公開的,所以是合法的。其實就像瀏覽器一樣,瀏覽器解析響應內容並渲染為頁面,而爬蟲解析響應內容採集想要的資料進行儲存。


反爬蟲

爬蟲很難完全的制止,道高一尺魔高一丈,這是一場沒有硝煙的戰爭,碼農VS碼農
反爬蟲一些手段:

  • 合法檢測:請求校驗(useragent,referer,介面加簽名,等)
  • 小黑屋:IP/使用者限制請求頻率,或者直接攔截
  • 投毒:反爬蟲高境界可以不用攔截,攔截是一時的,投毒返回虛假資料,可以誤導競品決策
  • … …

爬蟲基本套路

  • 基本流程
    • 目標資料
    • 來源地址
    • 結構分析
    • 實現構思
    • 操刀編碼
  • 基本手段
    • 破解請求限制
      • 請求頭設定,如:useragant為有效客戶端
      • 控制請求頻率(根據實際情景)
      • IP代理
      • 簽名/加密引數從html/cookie/js分析
    • 破解登入授權
      • 請求帶上使用者cookie資訊
    • 破解驗證碼
      • 簡單的驗證碼可以使用識圖讀驗證碼第三方庫
  • 解析資料
    • HTML Dom解析
      • 正則匹配,通過的正規表示式來匹配想要爬取的資料,如:有些資料不是在html 標籤裡,而是在html的script 標籤的js變數中
      • 使用第三方庫解析html dom,比較喜歡類jquery的庫
    • 資料字串
      • 正則匹配(根據情景使用)
      • 轉 JSON/XML 物件進行解析

python爬蟲

  • python寫爬蟲的優勢
    • python語法易學,容易上手
    • 社群活躍,實現方案多可參考
    • 各種功能包豐富
    • 少量程式碼即可完成強大功能
  • 涉及模組包
    • 請求
      • urllib
      • urllib2
      • cookielib
    • 多執行緒
      • threading
    • 正則
      • re
    • json解析
      • json
    • html dom解析
      • pyquery
      • beautiful soup
    • 操作瀏覽器
      • selenium

例項解析

鬥魚主播排行

  • 目標資料
    • 獲取排行榜主播資訊
  • 來源地址
  • 結構分析
    • 通過抓包 [排行榜地址][主播房間地址] (谷歌除錯network/charles/fiddler)
      • 獲得排行資料介面:https://www.douyu.com/directory/rank_list/game
        • 引數確認(去掉不必要引數)
        • cookie確認(去掉不必要cookie)
        • 模擬請求(charles/fiddler/postman)
      • 獲得主播房間資訊資料
        • 發現$ROOM是主播房間資訊,在頁面的script標籤的js變數中,可使用正則工具寫表示式去匹配
  • 實現構思
    • 通過請求 [主播排行介面] 獲取 [排行榜資料]
    • [排行榜資料] 中有主播房間號,可以通過拼接獲得 [主播房間地址]
    • 請求 [主播房間地址] 可以獲得 [$ROOM資訊] ,解析可以獲得主播房間資訊
  • 操刀編碼

申明:此例子僅作為爬蟲學習DEMO,並無其他利用


基於python實現爬蟲學習基礎demo

def douyu_rank(rankName, statType):
    ```
        鬥魚主播排行資料抓取
        [資料地址](https://www.douyu.com/directory/rank_list/game)

        * `rankName` anchor(巨星主播榜),fans(主播粉絲榜),haoyou(土豪實力榜),user(主播壕友榜)
        * `statType` day(日),week(周),month(月)
    ```
    if not isinstance(rankName, ERankName):
        raise Exception("rankName 型別錯誤,必須是ERankName列舉")
    if not isinstance(statType, EStatType):
        raise Exception("statType 型別錯誤,必須是EStatType列舉")

    rankName = `%sListData` % rankName.name
    statType = `%sListData` % statType.name
    # 請求獲取html原始碼 
    rs = rq.get(
        "https://www.douyu.com/directory/rank_list/game",
        headers={`User-Agent`: `Mozilla/5.0`})
    # 正則解析出資料
    mt = re.search(r`rankListDatas+?=(.*?);`, rs, re.S)
    if (not mt):
        print u"無法解析rankListData資料"
        return
    grps = mt.groups()
    # 資料轉json
    rankListDataStr = grps[0]
    rankListData = json.loads(rankListDataStr)
    dayList = rankListData[rankName][statType]
    # 修改排序
    dayList.sort(key=lambda k: (k.get(`id`, 0)), reverse=False)
    return dayList


def douyu_room(romm_id):
    ```
        主播房間資訊解析
        [資料地址](https://www.douyu.com/xxx)
        `romm_id` 主播房號
    ```
    rs = rq.get(
        ("https://www.douyu.com/%s" % romm_id),
        headers={`User-Agent`: `Mozilla/5.0`})
    mt = re.search(r`$ROOMs+?=s+?({.*?});`, rs, re.S)
    if (not mt):
        print u"無法解析ROOM資料"
        return
    grps = mt.groups()
    roomDataStr = grps[0]
    roomData = json.loads(roomDataStr)
    return roomData

def run():
    ```
        測試爬蟲
    ```
    datas = douyu_rank(ERankName.anchor, EStatType.month)
    print `
主播排行榜:`
    for item in datas:
        room_id = item[`room_id`]
        roomData = douyu_room(room_id)
        rommName = None
        if roomData is not None:
            rommName = roomData[`room_name`]
        roomInfo = (u`房間(%s):%s` % (item[`room_id`], rommName))
        print item[`id`], item[
            `nickname`], roomInfo, `[` + item[`catagory`] + `]`


run()

執行結果:

主播排行榜:

無法解析ROOM資料
1 馮提莫 房間(71017):None [英雄聯盟]
2 阿冷aleng丶 房間(2371789):又是我最喜歡的阿冷ktv時間~ [英雄聯盟]
3 勝哥002 房間(414818):勝哥:南通的雨下的我好心累。 [DNF]
4 White55開解說 房間(138286):盧本偉五五開 每天都要很強 [英雄聯盟]
5 東北大鵪鶉 房間(96291):東北大鵪鶉 宇宙第一寒冰 相聲藝術家! [英雄聯盟]
6 老實敦厚的笑笑 房間(154537):德雲色 給兄弟們賠個不是 [英雄聯盟]
7 劉飛兒faye 房間(265438):劉飛兒  月底吃雞 大吉大利 [絕地求生]
8 pigff 房間(24422):【PIGFF】借基地直播,沒OW [守望先鋒]
9 雲彩上的翅膀 房間(28101):翅:還是抽天空套刺激! [DNF]
10 yyfyyf 房間(58428):無盡的9月,殺 [DOTA2]

# 馮提莫 房間做週年主題,解析會有問題

Demo原始碼地址