2014年12月29日 星期一

[Python][教學] 網路爬蟲(crawler)實務(下)--爬蟲策略以及設定


       
        在知道目標之後,接著就要決定如何達成。網路爬蟲的概念很簡單,就是進入網頁之後,將網站中的原始碼擷取下來,透過Xpath或是Html節點的方式來找到目標字串。根據上次[Python][教學] 網路爬蟲(crawler)實務(上)--網頁元件解析分析的內容,我們的爬網策略大致上會是:

  • 進入搜尋頁面>找到店家網址>進入店家頁面>擷取資料
根據這樣的流程,將他拆解成更符合爬蟲程式的邏輯:
  • 進入搜尋頁面
  • 搜尋頁面有多個頁面,透過參數一次抓取n個搜尋頁面(搜尋網頁數n)
  • 從搜尋頁面中解析出店家的網址,每頁有m個店家網址(店家網頁數m)
  • 進入店家網址,解析出需要用的資訊(搜尋網頁數=n * m)
廢話不多說直接看code:
  • 這次的爬網流程雖然簡單,但是還是有幾個要注意的地方:
  1. time.sleep: 這次總共抓了n * m 個網頁,短時間的大量抓取會消耗網站資源,影響網站運行,所以通常有品的爬網者會設定睡眠時間,避免造成對方主機的負擔
  2. try except: 當需要自動抓大量欄位時,一定要考慮或是注意到你要抓的欄位可能不是每個頁面都有提供,所以要加上例外處理才能避免錯誤而跳出程式
  3. 更為普遍的xpath設定: 如果只抓一兩個頁面,xpath要怎樣設都可以,也可以很簡單的利用數數的方式去取得標籤。但是如果要抓大量網頁,每個網頁的每個節點的數量可能會不一樣,最好多看幾個網頁原始碼,找到每個標籤在結構上的固定位置,避免抓錯欄位。


24 則留言:

  1. 你好 我是teddy 請問你第13行的 str(i+1),是做什麼用的?
    當作變數來翻頁嗎?

    回覆刪除
    回覆
    1. 不是欸,那是一個List Comprehensive,一次產生一串網址用的

      刪除
  2. 請問你的程式是怎麼Run的,比如說要爬一個網站的載點網址 伊莉討論區-->電影下載區-->玩命關頭-->把網站載點爬下來 是這樣嗎?
    還有可不可以把你程式附註解然後寄給我,因為才剛開始學PYTHON,不知道行不行,如果不行就不用麻煩了,謝謝。

    回覆刪除
    回覆
    1. 或者貼到我的部落格裏面http://xeriom90862.blogspot.tw/

      刪除
    2. 您好,我的程式都已經貼上來了(汗)裡面也有註解(汗汗)
      我是用ipython來執行的

      刪除
    3. 作者已經移除這則留言。

      刪除
    4. 想跟你詢問一下我有跑過你的程式但她總是跟我說你程式第13行錯誤,請問這有什麼問題嗎,是我沒安裝好模塊嗎

      刪除
  3. 方便留下錯誤訊息嗎? 我這邊程式沒有錯誤喔

    回覆刪除
  4. 以解決了,不好意思,另外我想跟您請教一下該如何用PYTHON下載種子載點到指定目錄下(目前卡在怎樣丟到指定目錄下)

    回覆刪除
    回覆
    1. 請參考:
      import urllib2
      mp3file = urllib2.urlopen("http://www.example.com/songs/mp3.mp3")
      output = open('test.mp3','wb') #可用絕對路徑修改目標目錄
      output.write(mp3file.read())
      output.close()

      刪除
    2. 作者已經移除這則留言。

      刪除
  5. shop = header.h1.string.strip()
    請問為何這行會有錯誤
    ttributeError: 'NoneType' object has no attribute 'h1'

    初學python問題比較淺 感謝Bryan 大大指教

    回覆刪除
    回覆
    1. 又或者我想抓他下方的



      商家名稱
      XXX shop name

      都抓不出來
      可能語法錯了都報
      'NoneType' object has no attribute 'find_all'
      可否開示,感恩您~~

      刪除
    2. 被擋了
      div id="shop-details" 那邊

      刪除
    3. 因為header有欄位沒抓東西,所以變成NoneType,可以檢查一下header抓到的內容是部分還是全部錯誤,部分錯誤的話可以設try except排除

      刪除
    4. 我也是在執行
      header = soup.find('div',{'class':'info'})
      這行的時候他傳回的是一個空的list
      想請問一下為甚麼會這樣還有該怎麼解決?

      另外想問一下你的程式碼是用findAll()這個跟官方文件的find_all()是一樣的嗎?

      刪除
    5. 因為網頁改版了 原本的位置抓不到了XD
      請大家自行看原始HTML修改囉(怕太容易造成網頁困擾)

      刪除
    6. 很淺顯易懂的文章,對初入門的我幫助很大,看到資料整理出來的感覺很棒,謝謝囉!

      刪除
  6. 你好 想跟你詢問第19行的程式碼 -> [tag['href'] 這是什麼意思?

    ps 超愛你的程式碼 簡單好懂!

    回覆刪除
    回覆
    1. 謝謝您的喜歡:)
      [tag['href'] for tag in shop_link.findAll('a',{'href':True})]
      這是一個python的 comprehensive list, tag for tag in shop_link 表示從後面的shop_link.find取出各別元素並命名成tag,
      tag['href'], 表示從每個tag裡面,取出['href']中的字串

      刪除