1. 程式人生 > >Python3學習(34)--簡單網頁內容抓取(爬蟲入門一)

Python3學習(34)--簡單網頁內容抓取(爬蟲入門一)

基礎講多了也不好,懂的人看了煩躁,半懂的人看多了沒耐心,我也不能打消了你們學習Python的積極性了,開始爬蟲系列基礎篇之前,先上一張圖,給大腦充充血:


很多人,學習Python,無非兩個目的,一個就是純粹玩(確實好玩),一個就是為了上面這張毛爺爺(確實能換錢),羨慕,我是二者兼有,至少不清高,也不愛財。

在Python中,有一個模組,叫urllib,專門就是為了讀取web頁面中的資料,還記得Python的鴨子型別嗎,“file-like object”,走起路子只要像鴨子,那麼它就可以被當做鴨子。因此,我們可以像讀寫本地檔案那樣去讀寫web資料,只要拿到url,我們就可以拿到我們需要的物件,只要拿到物件,我們就可以賦予鴨子生命,從而享受美味的鴨肉(data)

直接上demo,說再多,不如敲一遍demo,親自感受一下

getHtml.py

#!/usr/bin/env Python3
# -*- encoding:utf-8 *-*

'''@author = 'Appleyk'  '''
'''@time   = '2017年9月23日11:42:32' '''

from urllib import request

def getResponse(url):
    #url請求物件 Request是一個類
    url_request = request.Request(url)
    print("這個物件的方法是:",url_request.get_method())
    
    #上下文管理器,HTTPResponse 物件,包含一系列方法
    url_response = request.urlopen(url) #開啟一個url或者一個Request物件
    '''
       geturl():返回 full_url地址
         info(): 返回頁面的元(Html的meta標籤)資訊
         <meta>:可提供有關頁面的元資訊(meta-information),比如針對搜尋引擎和更新頻度的描述和關鍵詞。
      getcode(): 返回響應的HTTP狀態程式碼 
      100-199 用於指定客戶端應相應的某些動作。
      200-299 用於表示請求成功。      ------>  200
      300-399 用於已經移動的檔案並且常被包含在定位頭資訊中指定新的地址資訊。
      400-499 用於指出客戶端的錯誤。  ------>  404
      500-599 用於支援伺服器錯誤。 
         read(): 讀取網頁內容,注意解碼方式(避免中文和utf-8之間轉化出現亂碼)
    '''

    return url_response   #返回這個物件

http_response = getResponse("http://dzh.mop.com/") #拿到http請求後的上下文物件(HTTPResponse object)
print(http_response)  #列印這個物件

執行的結果,我們等會再放出來,我們先來介紹一下,urllib模組的request功能。

(1)首先你得去請求一個url地址(網址),拿到Request物件,或者你不拿到Request的物件,直接在第二步中,使用url地址(字串)也行

(2)其次,你要將這個Reques物件作為request.urlopen函式的引數,以獲得請求後的http上下文物件,也就是http response物件,這個物件,還是很有料的,正是我們所需要的,當然,引數也可以直接是一個url字串。

我們藉助Python自帶的解析器,利用help函式,參照原形,對(1)和(2)中提到的內容做進一步說明

url_request = request.Request(url)


url_response = request.urlopen(url) 或者 url_response = request.urlopen(url_request)

開啟一個URL型別的 url,既可以是一個字串也可以是一個Request物件

函式總是返回一個物件,一個可以工作的上下文管理器,其中具有的方法如下


具體說明,看demo裡面的註釋,下面,我們來列印一下這個response物件


使用HTTPResponse物件的方法

A、geturl()


B、 info()


C、getcode()


D、read()


我們拿到了網頁內容,我們要幹嘛呢?  我們翻一下,這個網頁,看能不能找到一些圖片的url資訊(當然,博主肯定是事先在瀏覽其中打開了這個url地址,不然,我們怎麼能返回200呢!)


還真有,但是有多少個呢,我們引入re模板庫,使用正則表示式,列出來這些xxxxxx.jpg有多少個(何必親自一個個去數呢),demo改進如下:

getHtml.py:

#!/usr/bin/env Python3
# -*- encoding:utf-8 *-*

'''@author = 'Appleyk'  '''
'''@time   = '2017年9月23日11:42:32' '''

from urllib import request
import re   #使用正則表示式

def getResponse(url):
    #url請求物件 Request是一個類
    url_request = request.Request(url)
    #print("Request物件的方法是:",url_request.get_method())
    
    #上下文使用的物件,包含一系列方法
    #url_response = request.urlopen(url) #開啟一個url或者一個Request物件
    url_response = request.urlopen(url_request)
    '''
       geturl():返回 full_url地址
         info(): 返回頁面的元(Html的meta標籤)資訊
         <meta>:可提供有關頁面的元資訊(meta-information),比如針對搜尋引擎和更新頻度的描述和關鍵詞。
      getcode(): 返回響應的HTTP狀態程式碼 
      100-199 用於指定客戶端應相應的某些動作。
      200-299 用於表示請求成功。      ------>  200
      300-399 用於已經移動的檔案並且常被包含在定位頭資訊中指定新的地址資訊。
      400-499 用於指出客戶端的錯誤。  ------>  404
      500-599 用於支援伺服器錯誤。 
         read(): 讀取網頁內容,注意解碼方式(避免中文和utf-8之間轉化出現亂碼)
    '''

    return url_response   #返回這個物件

def getJpg(data):
    jpglist = re.findall(r'src="http.+?.jpg"',data)
    return  jpglist

http_response = getResponse("http://dzh.mop.com/") #拿到http請求後的上下文物件(HTTPResponse object)
#print(http_response.read().decode('utf-8'))
data = http_response.read().decode('utf-8')
L = getJpg(data)

global n  #宣告全域性變數n
n = 1
for jpginfo in L:
    print(n,'--->',jpginfo)
    n = n+1



執行下,看下效果:


怎麼下載到本地呢?很簡單,urllib模板庫,給我們提供的有現成的方法,如下


request的方法urlretrieve,只需要傳前兩個引數,一個是圖片的url地址,一個是圖片的本地檔名稱

方法說明:............指向本地磁碟,說白了就是下載

注意,我們要的不是

src="http://images01.mopimg.cn/imgs/20170922/20170922112551_0e2a19a344fb2f1c27ef438365587a78.jpg"

而是src的值--->

  http://images01.mopimg.cn/imgs/20170922/20170922112551_0e2a19a344fb2f1c27ef438365587a78.jpg

因此,我們需要在上述demo的基礎上再定義一個下載方法,給urlretrieve函式傳第一個引數的時候,需要再次用到正則表示式,來得到真正意義上的  url 圖片 地址!

直接上終極demo,如下

gethtml.py:

#!/usr/bin/env Python3
# -*- encoding:utf-8 *-*

'''@author = 'Appleyk'  '''
'''@time   = '2017年9月23日11:42:32' '''

from urllib import request
import re   #使用正則表示式

def getResponse(url):
    #url請求物件 Request是一個類
    url_request = request.Request(url)
    #print("Request物件的方法是:",url_request.get_method())
    
    #上下文使用的物件,包含一系列方法
    #url_response = request.urlopen(url) #開啟一個url或者一個Request物件
    url_response = request.urlopen(url_request)
    '''
       geturl():返回 full_url地址
         info(): 返回頁面的元(Html的meta標籤)資訊
         <meta>:可提供有關頁面的元資訊(meta-information),比如針對搜尋引擎和更新頻度的描述和關鍵詞。
      getcode(): 返回響應的HTTP狀態程式碼 
      100-199 用於指定客戶端應相應的某些動作。
      200-299 用於表示請求成功。      ------>  200
      300-399 用於已經移動的檔案並且常被包含在定位頭資訊中指定新的地址資訊。
      400-499 用於指出客戶端的錯誤。  ------>  404
      500-599 用於支援伺服器錯誤。 
         read(): 讀取網頁內容,注意解碼方式(避免中文和utf-8之間轉化出現亂碼)
    '''

    return url_response   #返回這個物件

def getJpg(data):
    jpglist = re.findall(r'src="http.+?.jpg"',data)
    return  jpglist
def downLoad(jpgUrl,n):
    #request.urlretrieve(jpg_link, path)
    try:
        request.urlretrieve(jpgUrl,'%s.jpg'  %n)   
    except Exception as e:
        print(e)
    finally:
        print('圖片%s下載操作完成' % n)
    

http_response = getResponse("http://dzh.mop.com/") #拿到http請求後的上下文物件(HTTPResponse object)
#print(http_response.read().decode('utf-8'))
data = http_response.read().decode('utf-8')
#print(data)
global n 
n = 1
L = getJpg(data)
for jpginfo in L:
    print(jpginfo)
    s = re.findall(r'http.+?.jpg',jpginfo)
    downLoad(s[0],n)
    n= n +1
    

沒執行demo下載之前,我們看一下我們當前的可執行路徑


來,我們執行一下demo,真是滿懷期待,有點小忐忑


如果,你的網速很快的話,效果就是刷刷刷的,如果你的網速比較慢,這個效果就是一個個蹦出來的,我們檢查一下,是不是真的下載下來了(我保證,最開始的url地址裡面的圖片,我沒看過!)


美女警察在哪呢,在這兒呢,我們放大看


本篇作為一個入門級的爬蟲案例,意在說明,想要抓取web資源,必須先要進行url請求,然後就是一系列的物件操作,為什麼是入門級的呢?

(1)不涉及url迴圈遍歷

(2)不涉及多執行緒

(3)不涉及複雜正則表示式

(4)不涉及演算法

(5)不涉及資料層面的儲存

(6)不涉及網路頻寬

(7)..................................

等等等等,我們初學Python的時候,一上來就想要搞什麼爬蟲,你寫爬蟲,我寫蜘蛛,反正都是蟲子,我只想說,沒有那麼簡單,如果毛爺爺人人都好掙了,那就沒什麼技術可言了。 因此,打好基礎很重要,入門思想的培養很重要,心裡不浮躁也很重要,總之,在沒有兩把刷子之前,老老實實多看,多寫,多敲,多思考,借鑑別人的思想,來發揮自己的長處,有朝一日,你也是蟲師!