1. 程式人生 > 其它 >Urllib庫

Urllib庫

技術標籤:python

Urllb 庫是 Pythn 中一個最基本的網路請求庫。可以模擬瀏覽器的行為,向指定的伺服器傳送一個請求,並可以儲存伺服器返回的資料。
  • urlopen 函式:

    在 Python 的 urllib 庫中,所有和網路請求相關的方法,都被集到 urllib.request 模組下面。

urtopen 函式的基本使用:
from urllib import request
resp = request.urlopen('http://www.baidu.com')
print(resp.read())

​ 實際上,使用瀏覽器訪問百度,右鍵檢視原始碼。你會發現,跟我們剛才打印出來的資料是一模一樣的。也就是說,上面的三行程式碼就已經幫我們把百度的首頁的全部程式碼爬下來了。一個基本的 url 請求對應的python程式碼真的非常簡單。

以下對 urlopen 函式進行詳細的講解:

  1. url :請求的url。

  2. date:請求的date,如果設定了這個值,那麼將變成 post 請求。

  3. 返回值:返回值是一個 http.client.HTTPResponse 物件,這個物件是一個類檔案控制代碼物件。有 read(size)、readline 、readlines 以及 getcode 等方法。

    # 練習
    from urllib import request
    import pprint
    # print()函式可以實現輸出,可以輸出字串、數值、列表、字典等;而pprint模組,可以提供打印出任何python資料結構類和方法。
    resp =
    request.urlopen('http://www.baidu.com') pprint.pprint(resp.read()) # 讀出全部資料 print(resp.readline()) # 讀取第一行資料 print(resp.readlines(20)) # 讀取多行資料 print(resp.getcode()) # 獲取響應的狀態
  • urlretrieve 函式:

    • 這個函式可以方便的將網頁上的一個檔案儲存到本地。以下程式碼可以非常方便的將百度的首頁下載到本地:

      from urllib import request
      request.urlretrieve('http://www.baidu.com/'
      ,'baidu.html')
  • urlencode 函式:

    • 用瀏覽器傳送請求的時候,如果url中包含了中文或者其他特殊字元,那麼瀏覽器會自動的給我們進行編碼。而如果使用程式碼傳送請求,那麼就必須手動進行編碼,這時候就應該使用 urlencode 函式來實現。 urlencode 可以把字典資料轉換為 URL 編碼的資料。

      -例項程式碼:

      from urllib import parse
      data = {'name';'爬蟲基礎','greet';'hello world','age':100}
      qs = parse.urlencode(date)
      print(qs)	
      
      urlencode函式相關練習:
      # urlencode 函式的用法
      '''
      urlencode函式可以把字典資料轉換為URL編碼額資料
      '''
      from urllib import parse
      from urllib import request
      
      result={'name':'爬蟲基礎','greet':'hello world','age':100}
      qs = parse.urlencode(result)
      print(qs) # 列印輸出:name=%E7%88%AC%E8%99%AB%E5%9F%BA%E7%A1%80&greet=hello+world&age=100
      
      url = 'http://www.baidu.com/s'   #http://www.baidu.com/swd?劉德華
      params = {'wd':'劉德華'}
      qs1 = parse.urlencode(params) # 將劉德華字典資料轉換為URL編碼資料
      url1 = url + "?" + qs1   # 拼接在一起
      print(url1) # 打印出完整的連線地址
      resp = request.urlopen(url1) # 獲取網頁的資料
      print(resp.read()) 
      
  • parse_qs函式:

    • 可以將經過編碼後的url引數進行解碼。
      -例項程式碼如下:

      form urllib import parse
      qs = ""
      print(parse.parse_qs(qs))
      
    
    ```python
    相關練習:
    # parse_qs函式的用法:
    result={'name':'爬蟲基礎','greet':'hello world','age':100}
    qs = parse.urlencode(result)   # 先將字典資料進行編碼
    print(qs) # 輸出:name=%E7%88%AC%E8%99%AB%E5%9F%BA%E7%A1%80&greet=hello+world&age=100
    result = parse.parse_qs(qs) # 將編碼資料轉換為字典資料
    print(result) # 輸出:{'name': ['爬蟲基礎'], 'greet': ['hello world'], 'age': ['100']}

  • urlparse和urlsplit:

​ - 有時候拿到一個url,想要對這個url中的各個組成部分進行分割,那麼這時候就可以使用urlparse 或者是 urlsplit 來進行分割。

​ 例項程式碼:

# urlparse 和 urlsplit函式的用法:
from urllib import parse

url = 'http://www.baidu.com/s?wd=python&username=abc#1'

result1 = parse.urlparse(url)
print(result1)
# 輸出:ParseResult(scheme='http', netloc='www.baidu.com', path='/s', params='', query='wd=python&username=abc', fragment='1')
result2 = parse.urlsplit(url)
print(result2)
# 輸出:SplitResult(scheme='http', netloc='www.baidu.com', path='/s', query='wd=python&username=abc', fragment='1')
print('scheme:',result1.scheme) # scheme: http
print('netloc:',result1.netloc) # netloc: www.baidu.com
print('path:',result1.path) # path: /s
print('params:',result1.query) # params: wd=python&username=abc
print('fragment:',result1.fragment) # fragment: 1


urlparse 和 urlsplit 基本上是一模一樣的。唯一不一樣的地方是:'urlparse'裡面多了一個'params'屬性,而'urlsplit'沒有'params'這個屬性,url中的'parame'屬性用的也比較少。
  • request.Request類:

    • 如果要在請求的時候增加一些請求頭,那麼就必須使用 request.Request 類來實現。比如要增加一個User-Agent,例項程式碼如下:

      from urllib import request
      headers = {
      	'User-Agent':
      }'''
      request.Request類:
      如果要在請求的時候增加一些請求頭,那麼就必須使用 request.Request 類來實現。比如要增加一個User-Agent,例項程式碼如下:
      '''
      from urllib import request
      
      url = 'https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput='
      
      # resp = request.urlopen(url)
      # print(resp.read())
      headers = {
          'User-Agest':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'
      }
      
      resp = request.Request(url,headers=headers)
      
      qs = request.urlopen(resp)
      print(qs.read())
      

**爬蟲練習:豆瓣

proxyHandler處理器(代理設定)

​ 很多網站會檢測某一段時間某個IP的訪問次數(通過流量統計,系統日誌等),如果訪問次數多的不像正常人,它會禁止這個IP的訪問。所以我們可以設定一些代理設定,每隔一段時間換一個代理,就算IP被禁止,依然可以換個IP繼續爬取。

​ urllib中通過ProxyHandler來設定使用代理伺服器,下面程式碼說明如何使用自定義opener來使用代理:

from urllib import request
# 這個是沒有使用程式碼的
# resp = request.urlopen('http://httpbin.org/get')
# print(resp.read().decode("utf-8"))

# 這個是使用子代理的
handler = request.ProxyHander({"http":"218.66.161.88:31769"})

opener = request.build_opener(hander)
req = request.Request("http://httpbin.org/ip")
resp = opener.open(req)
print(resp.read())

​ 常用的代理有:

	* 西制免費代理IP:http://www.xicidaili.com/
	* 快代理:http://www.kuaidaili.com/
	* 代理雲:http://www.dailiyun.com/

ProxyHandler處理器(代理):

​ 1、代理的原理:在請求目的網站之前,先請求伺服器,然後讓代理伺服器去請求目的網站,代理伺服器拿到目的網站的資料後,再轉發給我們的程式碼。

​ 2、http://httpbin.org:這個網站可以方便的檢視http請求的一些引數。

​ 3、在程式碼中使用代理

  • 使用”urllib.request.ProxyHandler“,傳入一個代理,這個代理是一個字典,字典的key是"http" 或者 ”https“,依賴與代理伺服器能夠接收的型別,值是”ip:port“

  • 使用上一步驟建立的“handler”,以及“request.build_opener”建立一個“opener”物件。

  • 使用上一步建立的“opener”,呼叫“open”函式,發起請求。

    例項程式碼如下:

    from urllib 
    
    url = 'http://httpbin.org/ip'
    # 使用代理的
    # 1、使用ProxyHandler,傳入代理 構建一個handler
    handler = request.ProxyHandler({"http":"14.20.235.107:9797"})
    # 2、使用上面建立的handler構建一個opener
    opener = request.build_opener(handler)
    # 3、使用opener去傳送一個請求
    resp = opener.open(url)
    print(resp.read())
    

常用的代理:

  • 西制免費代理IP:http://www.xicidaili.com/

  • 快代理:http://www.kuaidaili.com/

  • 代理雲:http://www.dailiyun.com/

  • cookie

    什麼是cookie:

    ​ 在網站中,http請求是無狀態的。也就是說即使第一次和伺服器連結後並且登入成功後,第二次請求伺服器依然不能知道當前請求是哪個使用者。cookie的出現就是為了解決這個問題,第一次登入後伺服器返回一些資料(coolie)給瀏覽器,然後瀏覽器儲存砸本地,當該使用者傳送第二次請求的時候,就會自動的把上次請求儲存的 coolie 資料自動的攜帶給伺服器,伺服器通過瀏覽器攜帶的資料就能判斷當前使用者是哪個了。coolie儲存的資料量有限,不同的瀏覽器有不同的儲存大小,但一般不超過4kb。因此使用coolie只能儲存一些小量的資料。

  • cookie****的格式:

​ Set-Cookie:NAME=VALUE:Expires/Max-age-DATE:Path+PATH:Domain=DOMAIN_NAME:SECURE

  • ​ 引數意義:

    • NAME:cookie的名字。
    • VALUE:cookie的值。
    • Expires:cookie的過期時間。
    • Path:cookie作用的路徑。
    • Domain:cookie作用的域名。
    • SECURE:是否只在HTTPS協議下起作用。
  • 使用cookielib庫和HTTPCookieProcessor模擬登入:

    ​ Coolie 是指網站伺服器為了辨別使用者身份和進行Session跟蹤,而儲存在使用者瀏覽器上的文字檔案,cookie可以保持登入資訊到使用者下次與伺服器的會話:

    ​ 這裡以人人網為例。人人網中,要訪問某個人的主頁,必須先登入才能訪問,登入說白了就是要有cookie資訊,那麼如果我們想要用程式碼的方式訪問,就必須要有正確的cookie資訊才能訪問。解決方案有兩種,第一種是使用瀏覽器訪問,然後將cookie資訊複製下來,放到headers中。例項程式碼如下:

第一種:

#使用cookie可以實現模擬登陸的狀態

​ From urllib import request

​ #大鵬董成主頁:http://www.renren.com/880151247/profile

​ #人人網登陸:http://www.renren.com/PLogin.do

# cookie使用方式一
# 1、不使用cookie去請求大鵬的主頁
depeng_url = "http://www.renren.com/880151247/profile"
headers = {
    'User-Agent':"Mozilla/5.0 (Windows NT 10.0"
                 "; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36",
    'Cookie':"anonymid=ki9qkk68-m4vjb6; depovince=ZGQT; _r01_=1; taihe_bi_sdk_uid=e9dd17147d9bd199dee38eae7f"
             "956b79; wp_fold=0; taihe_bi_sdk_session=502aff0aec39a22ee93f38240f0719b9; JSESSIONID=abcI3qYv"
             "RznIsehBK5Syx; t=a6a7a07491c536b0a776e4eac98be5249; societyguester=a6a7a07491c536b0a776e4eac9"
             "8be5249; id=975486549; xnsid=d319569c; ver=7.0; loginfrom=null; jebecookies=f0f20ef5-f4a2-486d"
             "-9d23-be5893e11d09|||||"
}
req = request.Request(url = depeng_url,headers = headers)
resp = request.urlopen(req)
# print(resp.read().decode('utf-8'))

# 將獲取到的資料儲存到本地
with open('renren.html','w',encoding='utf-8') as fp:
    # write 函式必須寫入一個str的資料型別
    # resp.read()讀出來的是一個bytes資料型別
    # bytes -> decode(解碼) -> str
    # str -> encode(編碼) -> bytes
    fp.write(resp.read().decode('utf-8'))

第二種

# cookie使用方式二
from urllib import request
from urllib import parse
from http.cookiejar import CookieJar
from ProxyHandler import opener
# 大鵬董成主頁:http://www.renren.com/880151247/profile
# 人人網登陸:http://www.renren.com/PLogin.do
headers = {
    'User-Agent':"Mozilla/5.0 (Windows NT 10.0"
                 "; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
}

def get_opener():
    # 1、登入
    # 1.1 建立一個cookiejar物件
    cookiejar = CookieJar()
    # 1.2 使用cookiejar建立一個HTTPPCookieProoess物件
    handler = request.HTTPCookieProcessor(cookiejar)
    # 1.3 使用上一步建立的handler建立一個opener
    handler = request.build_opener(handler)
    return opener

def login_renren(opener):
    # 1.4 使用opener傳送登入的請求(人人網的郵箱和密碼
    data = {
        'emali':"[email protected]",
        'password':"pythonspider"
    }
    login_url = "http://www.renren.com/PLogin.do"
    req = request.Request(login_url,data = parse.urlencode(data).encode('utf-8'),headers = headers)
    opener.open(req)

def visit_profile(opener):
    # 2、訪問個人主頁
    dapeng_url = "http://www.renren.com/880151247/profile"
    # 獲取個人主頁的資訊的時候,不要新家一個opener
    # 而應該使用之前的那個opener,因為之前的那個opener已經包含了
    # 登入所需要的cookie資訊
    req = request.Request(dapeng_url,headers=headers)
    resp = opener.open(req)
    with open('renren1.html',"w",encoding="utf-8") as fp:
        fp.write(resp.read().decode("utf-8"))


if __name__ == '__main__':
    opener = get_opener()
    login_renren(opener)
    visit_profile(opener)
  • 儲存cookie到本地

    ​ 儲存 cookie 到本地,可以使用 cookiejar 的 save 方法,並且需要指定一個檔名:

# 儲存 cookie 到本地,可以使用 cookiejar 的 save 方法,並且需要指定一個檔名:
from urllib import request
from http.cookiejar import MozillaCookieJar

cookiejar = MozillaCookieJar('cookie.txt')
# cookiejar.load(ignore_discard=True) 把已經過期的cookie資訊列印進來 
handler = request.HTTPCookieProcessor(cookiejar)
opener = request.build_opener(handler)

# 向百度傳送一個請求
resp = opener.open('http://www.baidu.com/')
# 列印返回值,得到的是cookie資訊,也可以不用列印
# 儲存百度的cookie資訊
cookiejar.save()
#cookiejar.save(ignore_discard=True) # 儲存即將過期的cooker資訊