Python "爬蟲"出發前的裝備之二資料先行( Requests 模組)

一枚大果殼發表於2022-03-03

1. 概念

爬蟲不是動物,而是一種計算機程式。

這種程式有自己特定的功能,能按照使用者給定的一系列規則自行瀏覽全球資訊網並獲取需要的資訊。此類程式被稱為 網路爬蟲(web crawler)網路蜘蛛(spider)
它具有智慧分析能力,也稱為 機器人程式

爬蟲的應用應用領域:

如百度、谷歌等以搜尋為主的公司,就是利用其自行研發的爬蟲程式在網際網路上對網頁中的資料進行爬取、分析、歸類、儲存……再提供給使用者使用。
新聞聚合應用也是利用爬蟲程式爬取各新聞網站上的新聞資訊,進行分檢歸類後提供給使用者。

爬蟲程式可運用於各種需要資料分析的應用領域。如價格分析,根據商品關鍵字爬取各商城中商品價格,對價格進行比較、分析後展示給使用者一個直觀的對比表。

爬蟲程式從網路上爬取資料時,需要遵守 Rebots 協議。

Rebots 協議是網站擬定的資源共享清單,規定爬蟲在本網站爬取資料時,哪些資源可以爬取,哪些資源不可以爬取。

爬蟲程式的工作流程:

  1. 確定目標網頁。此頁為起始頁或叫入口頁面
  2. 獲取頁面的資料,通過某種方式(如正規表示式)獲取頁面中的相關資訊。並可提取頁面中連結,以遞迴方式繼續對頁面資料進行分析,提取。
  3. 將資訊持久化儲存,可備後續的處理。

2. Python 爬蟲模組

爬蟲程式的核心邏輯之一便是通過網路請求模式,下載指定頁面的資料。

爬蟲程式的本質就是一個網路應用程式

Python 提供了豐富的庫或模組可協助開發者快速開發此類網路應用程式。

2.1 urllib 庫

urllib 庫是 python 內建庫,不需要另外安裝。完整的 urllib 庫包括如下 5 大模組:

  • urllib.request :可使用不同的協議傳送請求包並獲取請求之後的響應結果。
  • urllib.response :用來解析響應包資料。
  • urllib.error: 包含了 urllib.request 產生的異常。
  • urllib.parse: 用來解析和處理 URL。
  • urllib.robotparse: 用來解析頁面的 robots.txt 檔案。

使用 urllib.request 模組傳送網路請求:

import urllib.request
# 基於 https 協議的 url 地址
url = "https://www.cnblogs.com/guo-ke/p/15951196.html"
# 構建一個請求物件
req = urllib.request.Request(url)
# 使用 urlopen 方法傳送請求包
with urllib.request.urlopen(req) as resp:
    # 解析資料
    data = resp.read()
    print(data.decode())
  1. urllib.request.Request() 類說明:構建請求包。

類原型宣告:

class Request:
   def __init__(self, url, data=None, headers={},origin_req_host=None, unverifiable=False,method=None):
           #…… 其它程式碼塊

構造方法引數說明

  • url:要請求的 url 地址 。

  • data:data 必須是bytes(位元組流)型別,如果是字典,可以用 urllib.parse 模組裡的 urlencode( ) 編碼

  • headers:headers 是一個字典型別,用來描述請求頭資訊。

    可在構造方法中指定,也可以通過呼叫 add_header( ) 方法新增

    預設 User-AgentPython-urllib

  • origin_req_host:指定請求方的 host 名稱或者 ip 地址。

  • unverifiable:設定網頁是否需要驗證,預設是 False。

  • method:用來指定請求使用的方法,如 **GET、POST 或 PUT ** 等。

很多網站具有反爬蟲設定,除了瀏覽器之外的訪問均認定為非法請求。所以爬蟲程式需要把自己偽裝成瀏覽器。

from urllib import request, parse

url = 'http://www.guo-ke.com/post' 
headers = {
    # 偽裝成谷歌瀏覽器
	'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36',
	'Host': 'guo-ke.org'
}
dict = {
	'name': 'guoke',
    'key':'python'
}
# 資料必須是位元組流
data = bytes(parse.urlencode(dict), encoding='utf8')
'''
# 轉換成 URL 格式的字串
data = parse.urlencode(dict)
# 編碼成位元組流資料
data = data.encode()
'''
request = request.Request(url=url, data=data, headers=headers, method='POST')
# req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36')
with  request.urlopen(req) as response:
    res=(response.read()
	print(res.decode('utf-8'))

Tip:當使用了 data 引數或指定 method="POST" 則為POST 請求。

GET 請求也能附加請求引數:https://www.baidu.com/s?wd=java

  1. urllib.request.urlopen( ) 方法說明:傳送網路請求。
def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
            *, cafile=None, capath=None, cadefault=False, context=None):

引數說明:

  • url: 可以接收一個 URL 字串 或一個 urllib.request.Request 物件

  • data: POST 請求時的資料,GET 請求設定為 None。

  • timeout: 設定網站的訪問超時時間。僅僅用於使用 HTTP、HTTPS、FTP 協議請求連線時。

  • cafile、capath: 當使用 HTTPS 請求時,用來指定 CA 數字證照。

    cafile 指定數字證照檔案。

    capath 指定包含的數字認證檔案的目錄。

返回型別說明:無論使用何種協議傳送請求後返回的物件都會包括 3 個通用方法。

  • geturl( ) 返回請求的資源URL。

  • info( ) 返回後設資料資訊,如訊息頭。

  • getcode( ) 返回響應的狀態碼. 如果有錯誤則會丟擲 URLError 異常。

當使用 httphttps 協議請求後返回的是一個 http.client.HTTPResponse 物件,此物件除了上面的 3 個方法,還包括:

  • read( ): 獲取響應返回的 bytes 型別資料,只能使用一次,輸出時需要使用 decode() 解碼。
  • getheaders( ): 獲取返回的響應頭資訊。

使用 urllib.request 下載一張圖片:

爬蟲程式強大之處在於能批量、遞迴下載使用者所需要的資料,一個強大的邏輯背後的思想可能就是一個簡單的原理支撐的。我們可以先試著下載一張圖片以小窺大。

import urllib.request

# 圖片URL
url = "https://img2022.cnblogs.com/blog/2749732/202202/2749732-20220222195931956-448995015.jpg"
with urllib.request.urlopen(url) as resp:
    data = resp.read()
    with open("d:/my_file.jpg", "wb") as f:
        f.write(data)

開啟對應碟符,可以查閱到圖片已經下載成功。

urllib.request 還提供有一個更方便的 urlretrieve( ) 方法。可直接以檔案方式儲存下載下來的位元組流資料。

from urllib import request
url = "https://img2022.cnblogs.com/blog/2749732/202202/2749732-20220222195931956-448995015.jpg"
# urlretrieve() 方法傳入的第二個引數為檔案儲存的位置,以及檔名。
request.urlretrieve(url, 'd:/temp.jpg')

2.2. requests 庫

requests 是基於urllib 編寫的第三方庫,使用時,需要下載安裝:

pip3 install requests

主要提供了 2 個方法:

1. get( ) 方法用來傳送 GET 請求。

def get(url, params=None, **kwargs):
    #……

引數說明:

  • url:需要請求的 url 資源(字串型別)。
  • params:查詢資料,可以是字典、列表、元組、位元組型別。
  • kwargs:以鍵值對描述的請求訊息頭引數。

基本 GET 使用:

import requests

# 用get方式傳送請求並獲得響應
response = requests.get('https://www.cnblogs.com/guo-ke/p/15925214.html')
# 用text檢視響應內容
print(response.text)

帶引數 get 請求

import requests

response = requests.get('https://www.baidu.com/s?wd=java')
# 將引數拼接到url後面,用問號分隔,引數間用&來分隔
print(response.text)

字典格式的引數

import requests

data = {
    'wd': 'java'
}
response = requests.get('https://www.baidu.com/s', params=data)
# 用字典的形式傳遞給params引數,不需要自己寫url編碼
print(response.text)

GET 方法返回一個 Responese 物件,此物件提供有相應屬性或方法解析響應包中的資料。

  • response.encoding:獲取當前的編碼。
  • response.encoding = 'utf-8':設定編碼。
  • response.text:自動根據響應頭部的字元編碼進行解碼。
  • response.content:以位元組形式(二進位制)返回。
  • response.headers:以字典物件儲存伺服器響應頭,字典鍵不區分大小寫,若鍵不存在則返回 None。
  • response.status_code:響應狀態碼。
  • response.raw:返回原始響應體,也就是 urllib 的 response 物件,使用 response.raw.read()
  • response.json() :Requests 中內建的JSON解碼器,以json形式返回,前提返回的內容確保是json格式的,不然解析出錯會拋異常。

下載一張圖片

import requests
#;圖片地址
url = "https://img2022.cnblogs.com/blog/2749732/202202/2749732-20220222195931956-448995015.jpg"
#請求頭後設資料
headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'
}
response = requests.get(url, headers=headers)
# 獲取位元組流資料
data = response.content
#儲存位元組流資料
with open("d:/test.jpg", "wb") as f:
    f.write(data)

2. post() 方法:以 post 方式傳送請求

def post(url, data=None, json=None, **kwargs):

引數說明:

  • url:字串型別的需要請求的 url 資源。
  • data:傳送資料,可以是字典、列表、元組、位元組型別
  • json:json 格式的資料。
  • kwargs:以鍵值對描述的請求頭引數。

基本使用方式

import requests

data={'name':'zhuzhu','age':'23'}
headers={
 'User-Agent':'Mozilla/5.0(Macintosh;Intel Mac OS X 10_11_4)AppleWebKit/537.36(KHTML,like Gecko)Chrome/52.0.2743.116 Safari/537.36'
}
response=requests.post("http://httpbin.org/post",data=data,headers=headers)
#資料必須是json 封裝
print(response.json())

3. 總結

requests 在基於 urllib 編寫的第三方庫,相比較 urllib 使用起來更簡單。對其 API 介紹 ,本文只做了些簡單描述。更多方法或使用可查閱文件。

相關文章