1. 程式人生 > >python中的urllib模組中的方法

python中的urllib模組中的方法

python urllib.request之urlopen函式

urllib是基於http的高層庫,它有以下三個主要功能:

(1)request處理客戶端的請求

(2)response處理服務端的響應

(3)parse會解析url

下面討論的是request

urllib.request模組定義了一些開啟URLs(一般是HTTP協議)複雜操作像是basic 和摘要模式認證,重定向,cookies等的方法和類。這個模組式模擬檔案模組實現的,將本地的檔案路徑改為遠端的url。因此函式返回的是類檔案物件(file-like object)

urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)

url可以是一個字串形式或者Request 物件

如果data引數有值就是用post方式響應否則預設為GET 方式

urllib.request 模組使用HTTP/1.1 的無連線的狀態協議

urlopen()函式返回類檔案物件,提供以下內建方法:

-      read() , readline() ,readlines() , fileno() , close() :這些方法的使用方式與檔案物件完全一樣

-      info():返回一個httplib.HTTPMessage物件,表示遠端伺服器返回的頭資訊

-      getcode():返回Http狀態碼。(詳情參考https://tools.ietf.org/html/rfc7231#section-6)

                          如果是http請求:

                                                    1xx(informational):請求已經收到,正在進行中

                                                    2xx(successful):請求成功接收,解析,完成

                                                    3xx(Redirection):需要重定向

                                                    4xx(Client Error):客戶端問題,請求存在語法錯誤,網址未找到

                                                    5xx(Server Error):伺服器問題

-      geturl():返回請求的url

#!/opt/yrd_soft/bin/python

import re

import urllib2

import requests

import lxml

from bs4 import BeautifulSoup

url = 'http://www.baidu.com'

#page=urllib2.urlopen(url)

page=requests.get(url).text

pagesoup=BeautifulSoup(page,'lxml')

for link  in pagesoup.find_all(name='a',attrs={"href":re.compile(r'^http:')}):

    print link.get_text()

通過BeautifulSoup庫的get_text方法找到網頁的正文:

#!/usr/bin/env python

#coding=utf-8

#HTML找出正文

import requests

from bs4 import BeautifulSoup

url='http://www.baidu.com'

html=requests.get(url)

soup=BeautifulSoup(html.text)

print soup.get_text()

1  urllib2 簡介

    urllib2是python自帶的一個訪問網頁及本地檔案的庫。

    與urllib相比,顯著區別之處在於:

    1) urllib2可以接受一個Request類的例項來設定URL請求的headers,urllib僅可以接受URL。這意味著,用urllib時不可以偽裝User Agent字串等。

    2) urllib提供urlencode方法用來encode傳送的data,而urllib2沒有。這是為何urllib常和urllib2一起使用的原因。

2  urllib2 常用方法

 2.1  urllib2.urlopen

    urlopen()是最簡單的請求方式,它開啟url並返回類檔案物件,並且使用該物件可以讀取返回的內容

urllib2.urlopen(url[, data][, timeout]) 

引數:

    url: 可以是包含url的字串,也可以是urllib2.request類的例項。

    data: 是經過編碼的post資料(一般使用urllib.urlencode()來編碼)。

    沒有data引數時為GET請求,設定data引數時為POST請求

    timeout: 是可選的超時期(以秒為單位),設定請求阻塞的超時時間,如果沒有設定的話,會使用全域性預設timeout引數,該引數只對HTTP、HTTPS、FTP生效

假設urlopen()返回的檔案物件u,它支援下面的這些常用的方法:

u.read([nbytes]) 以位元組字串形式讀取nbytes個數據

u.readline() 以位元組字串形式讀取單行文字

u.readlines() 讀取所有輸入行然後返回一個列表

u.close() 關閉連結

u.getcode() 返回整數形式的HTTP響應程式碼,比如成功返回200,未找到檔案時返回404

u.geturl() 返回所返回的資料的實際url,但是會考慮發生的重定向問題

u.info() 返回對映物件,該物件帶有與url關聯的資訊。

對HTTP來說,返回的伺服器響應包含HTTP包頭。

對於FTP來說,返回的報頭包含'content-length'。

對於本地檔案,返回的報頭包含‘content-length’和'content-type'欄位。

注意:

    類檔案物件u以二進位制模式操作。如果需要以文字形式處理響應資料,則需要使用codecs模組或類似

方式解碼資料。

附程式碼:

>>> import urllib2

>>> res=urllib2.urlopen('http://www.51cto.com')

>>>res.read()

。。。。。。(一堆原始碼)

>>>res.readline()

'<!DOCTYPE html PUBLIC "-//W3C//DTDXHTML 1.0 

Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\r\n'

>>>res.readlines()

。。。(list形式的一堆原始碼)

>>>res.info()

<httplib.HTTPMessage instance at0x1a02638>

>>>res.getcode()

200

>>>res.geturl()

'http://www.51cto.com' 

#最後關閉連線

>>> res.close()

 2.2  urllib2.request

新建Request例項

 Request (url [data,headers[,origin_req_host ,[unverifiable]]]])

說明:

    對於比較簡單的請求,urlopen()的引數url就是一個代表url的,但如果需要執行更復雜的操作,如修改HTTP報頭,可以建立Request例項並將其作為url引數

引數:

    url: 為url字串,

    data: 是伴隨url提交的資料(比如要post的資料)。不過要注意,提供data引數時,它會將HTTP請求從'GET'改為‘POST’。

    headers: 是一個字典,包含了可表示HTTP報頭的鍵值對映(即要提交的header中包含的內容)。

    origin_req_host: 通常是發出請求的主機的名稱,如果請求的是無法驗證的url(通常是指不是使用者直接輸入的url,比如載入影象的頁面中鑲入的url),則後一個引數unverifiable設為TRUE 

假設Request例項r,其比較重要的方法有下面幾個:

r.add_data(data) 向請求新增資料。如果請求是HTTP請求,則方法改為‘POST’

data是向指定url提交的資料,要注意該方法不會將data追教導之前已經設定的任何資料上,而是使用現在的data替換之前的。

r.add_header(key, val) 向請求新增header資訊,key是報頭名,val是報頭值,兩個引數都是字串。

r.addunredirectedheader(key,val) 作用基本同上,但不會新增到重定向請求中。

r.set_proxy(host, type) 準備請求到伺服器。使用host替換原來的主機,使用type替換原來的請求型別。

附程式碼:

    1  向網頁提交資料:

>>> import urllib

>>> import urllib2

>>> url='http://www.51cto.com'

>>> info={'name':"51cto",'location':'51cto'}

#info需要被編碼為urllib2能理解的格式,這裡用到的是urllib

>>> data=urllib.urlencode(info)

>>> data

'name=51cto&location=51cto'

>>> request=urllib2.Request(url,data)

>>> response=urllib2.urlopen(request)

>>> the_page=response.read()

    2  修改網頁頭資訊:

    有時會碰到,程式也對,但是伺服器拒絕你的訪問。這是為什麼呢?問題出在請求中的頭資訊(header)。 有的服務端有潔癖,不喜歡程式來觸控它。這個時候你需要將你的程式偽裝成瀏覽器來發出請求。請求的方式就包含在header中。

    在使用 REST 介面時,Server 會檢查Content-Type欄位,用來確定 HTTP Body 中的內容該怎樣解析。

>>> import urllib

>>> import urllib2

>>> url='http://www.51cto.com'

# 將user_agent寫入頭資訊

>>> user_agent='Mozilla/4.0 (compatible; MSIE 5.5; WindowsNT)'

>>>values={'name':'51cto','location':"51cto",'language':'Python'} 

>>> headers={'User-Agent':user_agent}

>>> data=urllib.urlencode(values)

>>> req=urllib2.Request(url,data,headers)

>>> response=urllib2.urlopen(req)

>>> the_page=response.read()

  2.3  異常處理

    不能處理一個respons時,urlopen丟擲一個urlerror

urllib2.URLError:  

urllib2.HTTPError:

    HTTPerror是HTTP URL在特別的情況下被丟擲的URLError的一個子類。

    urlerror:

    通常,urlerror被丟擲是因為沒有網路 連線(沒有至特定伺服器的連線)或者特定的伺服器不存在。在這種情況下,含有reason屬性的異常將被丟擲,以一種包含錯誤程式碼 和文字錯誤資訊的tuple形式。

#!/usr/bin/env python

# -*- coding: utf-8 -*-

import urllib2

#多寫了一個 m (comm)

req = urllib2.Request('http://www.51cto.comm')

try:

    urllib2.urlopen(req)

except urllib2.URLError,e:

    print e

    print e.reason

結果:

 python之web模組學習,基本上涉及常用的的web模組,包括 urllib、urllib2、httplib、urlparse、requests,現在,開始我們的第一個模組的學習吧。

  1  urllib簡介 

    python urllib 模組提供了一個從指定的URL地址獲取網頁資料,然後對其進行分析處理,獲取我們想要的資料。

  2  常用方法

    2.1  urlopen  -- 建立一個類檔案物件 為讀取指定的URL

help(urllib.urlopen)

urlopen(url, data=None, proxies=None)

    Create a file-like object for the specified URL to read from.

引數:

    url :表示遠端資料的路徑,一般是http或者ftp路徑。

    data :表示以get或者post方式提交到url的資料。

    proxies :表示用於代理的設定。

Python 通過urlopen函式來獲取html資料,urlopen返回一個類檔案物件,它提供瞭如下常用方法:

    1)read() , readline() , readlines(),fileno()和close():這些方法的使用與檔案物件完全一樣。

    2)info():返回一個httplib.HTTPMessage 物件,表示遠端伺服器返回的頭資訊。

    3)getcode():返回Http狀態碼,如果是http請求,200表示請求成功完成;404表示網址未找到。

    4)geturl():返回請求的url地址。

附程式碼:

>>> import urllib

>>> response = urllib.urlopen('http://www.51cto.com') 

>>>res.read()

。。。。。。(一堆網頁程式碼)

>>>res.readline()

'<!DOCTYPE html PUBLIC "-//W3C//DTDXHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\r\n' 

。。。。

>>>res.readlines()

。。。(list形式的一堆網頁程式碼)

>>>res.info()

<httplib.HTTPMessage instance at0x1a02638>

>>> response.getcode()  # 返回Http狀態碼

    200

>>> response.geturl() # 返回請求的url地址 

    'http://www.51cto.com'

>>> response.close() # 最後別忘了關閉連線

urllib中還提供了一些輔助方法,用於對url進行編碼、解碼。url中是不能出現一些特殊的符號的,有些符號有特殊的用途。我們知道以get方式提交資料的時候,會在url中新增key=value這樣的字串,所以在value中是不允許有'=',因此要對其進行編碼;與此同時伺服器接收到這些引數的時候,要進行解碼,還原成原始的資料。這個時候,這些輔助方法會很有用:

    附帶的其他方法:(主要是url編碼解碼)

- urllib.quote(string[, safe]):對字串進行編碼。引數safe指定了不需要編碼的字元

- urllib.unquote(string) :對字串進行解碼

- urllib.quote_plus(string [ , safe ] ) :與urllib.quote類似,但這個方法用'+'來替換' ',而quote用'%20'來代替' '

- urllib.unquote_plus(string ) :對字串進行解碼

- urllib.urlencode(query[, doseq]):將dict或者包含兩個元素的元組列表轉換成url引數。例如 字典{'name': 'wklken', 'pwd':'123'}將被轉換為"name=wklken&pwd=123"  (常用)

#這裡可以與urlopen結合以實現post方法和get方法

- urllib.pathname2url(path):將本地路徑轉換成url路徑

- urllib.url2pathname(path):將url路徑轉換成本地路徑

附程式碼:

>>> import urllib

>>>res = urllib.quote('I am 51cto')

>>> res

'I%20am%2051cto'

>>>urllib.unquote(res)

'I am 51cto'

>>>res = urllib.quote_plus('I am 51cto')

>>> res

'I+am+51cto'

>>>urllib.unquote_plus(res)

'I am 51cto'

>>> params = {'name':'51cto','pwd':'51cto'}

>>>urllib.urlencode(params)

'pwd=51cto&name=51cto'

>>>l2u=urllib.pathname2url('E:\51cto')

'E%3A%29cto'

>>>urllib.url2pathname(l2u)

'E:)cto'

    2.2 urlretrieve -- 直接將遠端的資料下載到本地

help(urllib.urlretrieve)

urlretrieve(url, filename=None,reporthook=None, data=None)

引數:

    url :指定下載的URL

    finename :指定了儲存本地路徑(如果引數未指定,urllib會生成一個臨時檔案儲存資料。

    reporthook :是一個回撥函式,當連線上伺服器、以及相應的資料塊傳輸完畢時會觸發該回調,我們可以利用這個回撥函式來顯示當前的下載進度。

    data: 表示post到伺服器的資料,該方法返回一個包含兩個元素的(filename,headers)元組,

    下面是一個 urlretrieve方法下載檔案的例項,可以顯示下載進度:

#!/usr/bin/env python

# -*- coding: utf-8 -*-

import urllib

import os

def schedule(a,b,c):

    ''' 回撥函式

    @a:已經下載的資料

    @b:資料塊的大小

    @c:遠端檔案的大小

    '''

    per = 100.0 * a * b / c

    if per > 100:

        per = 100

    print "%.2f%%" % per

url = 'http://www.python.org/ftp/python/2.7.5/Python-2.7.5.tar.bz2'

local = os.path.join('c:','Python-2.7.5.tar.bz2')

urllib.urlretrieve(url,local,schedule)

    2.3  urlcleanup -- 清除由於urllib.urlretrieve()所產生的快取

    通過上面的練習可以知道,urlopen可以輕鬆獲取遠端html頁面資訊,然後通過python正則對所需要的資料進行分析,匹配出想要用的資料,然後利用urlretrieve將資料下載到本地。對於訪問受限或者對連線數有限制的遠端url地址可以採用proxies(代理的方式)連線,如果遠端資料量過大,單執行緒下載太慢的話可以採用多執行緒下載,這個就是傳說中的爬蟲。

    上面介紹的前兩個方法是urllib中最常用的方法,這些方法在獲取遠端資料的時候,內部會使用URLopener或者 FancyURLOpener類。作為urllib的使用者,我們很少會用到這兩個類。如果對urllib的實現感興趣,或者希望urllib支援更多的協議,可以研究這兩個類

urllib2是python自帶的模組,有簡單請求方法,也有複雜的http驗證,http代理方法,今天就介紹幾個基本的http請求方法。

urllib2的urlopen方法可以直接新增url即可訪問,但是此方法不支援驗證和代理的方法,所以後邊會介紹urllib2的Request類和opener

urllib2.urlopen

urllib2.urlopen(url,data=None,timeout=1,cafile=None,capath=None,cadefault=False,context=None)

下面是urllib2發起http請求,獲取httpcode

In [1]: import urllib2

In [2]: url = 'http://test.nginxs.net/index.html'

In [3]: res = urllib2.urlopen(url)

#讀取請求結果

In [5]: print res.read()

this is index.html

#獲取httpcode

In [6]: print res.code

200

#獲取http請求頭

In [7]: print res.headers

Server: nginxsweb

Date: Sat, 07 Jan 2017 02:42:10 GMT

Content-Type: text/html

Content-Length: 19

Last-Modified: Sat, 07 Jan 2017 01:04:12 GMT

Connection: close

ETag: "58703e8c-13"

Accept-Ranges: bytes

urllib2的Request

(self, url, data=None, headers={}, origin_req_host=None, unverifiable=False)

通過http請求傳送資料給zabbix登入(非api的登入)

import urllib

import urllib2

url = 'http://192.168.198.116/index.php'

#這裡是zabbix的賬戶,密碼,和點選的操作

data = {'name' : 'admin',

          'password' : 'zabbix',

          'enter' : 'Sign in' }

#編碼上面的資料

data = urllib.urlencode(data)

#例項化Request類

req = urllib2.Request(url, data)

#傳送請求

response = urllib2.urlopen(req)

the_page = response.read()

print the_page

urllib2.HTTPBasicAuthHandler

驗證nginx的使用者進行登入

#初始化一個auth_handler例項它的功能是http驗證的類

auth_handler = urllib2.HTTPBasicAuthHandler()

top_level_url = 'http://test.nginxs.net/limit/views.html'

username='admin'

password='nginxs.net'

#呼叫auth_handler例項裡面的密碼方法

auth_handler.add_password(realm='Nginxs.net  login',uri='

#構建一個opener 物件,它將使用http,https,ftp這三個預設的handlers

opener = urllib2.build_opener(auth_handler)

#安裝一個opener作為全域性urlopen()使用的物件

urllib2.install_opener(opener)

res=urllib2.urlopen(top_level_url)

print res.read()

urllib2.ProxyHandler

使用代理訪問一個網站

url='http://new.nginxs.net/ip.php'

#初始化一個名為proxy代理例項

proxy = urllib2.ProxyHandler({'http':'127.0.0.1:1080'})

#這裡建立一個opener物件,這個物件可以處理http,https,ftp等協議,如果你指定了子類引數這個預設的handler將不被使用

opener = urllib2.build_opener(proxy)

#使用open方法開啟url

res = opener.open(url)

#檢視返回結果

print res.read()

Python爬蟲主要使用的是urllib模組,Python2.x版本是urllib2,很多部落格裡面的示例都是使用urllib2的,因為我使用的是Python3.3.2,所以在文件裡面沒有urllib2這個模組,import的時候會報錯,找不到該模組,應該是已經將他們整合在一起了。

在Python 3以後的版本中,urllib2這個模組已經不單獨存在(也就是說當你import urllib2時,系統提示你沒這個模組),urllib2被合併到了urllib中,叫做urllib.request 和 urllib.error 。

urllib整個模組分為urllib.request, urllib.parse, urllib.error。

例: 

其中

urllib2.urlopen()變成了urllib.request.urlopen() 

urllib2.Request()變成了urllib.request.Request()

urllib和urllib2模組之間的區別

在python中,urllib和urllib2不可相互替代的。

整體來說,urllib2是urllib的增強,但是urllib中有urllib2中所沒有的函式。

urllib2可以用urllib2.openurl中設定Request引數,來修改Header頭。如果你訪問一個網站,想更改User Agent(可以偽裝你的瀏覽器),你就要用urllib2.

urllib支援設定編碼的函式,urllib.urlencode,在模擬登陸的時候,經常要post編碼之後的引數,所以要想不使用第三方庫完成模擬登入,你就需要使用urllib。

urllib一般和urllib2一起搭配使用

1.urllib.urlopen(url[,data[,proxies]])

開啟一個url的方法,返回一個檔案物件,然後可以進行類似檔案物件的操作。本例試著開啟baidu

import urllib

f = urllib.urlopen('http://www.baidu.com')

firstLine = f.readline()   #讀取html頁面的第一行

print firstLine

urlopen返回物件提供方法:

read() , readline() ,readlines() , fileno() , close() :這些方法的使用方式與檔案物件完全一樣

info():返回一個httplib.HTTPMessage物件,表示遠端伺服器返回的頭資訊

getcode():返回Http狀態碼。如果是http請求,200請求成功完成;404網址未找到

geturl():返回請求的url

2.urllib.urlretrieve(url[,filename[,reporthook[,data]]])

urlretrieve方法將url定位到的html檔案下載到你本地的硬碟中。如果不指定filename,則會存為臨時檔案。

urlretrieve()返回一個二元組(filename,mine_hdrs)

臨時存放:

#需要指定存放地址可用 filename = urllib.urlretrieve('http://www.baidu.com',filename='/path/baidu.html')

import urllib

filename = urllib.urlretrieve('http://www.baidu.com')

type(filename)

filename[0]

filename[1]

3.urllib.urlcleanup()

清除由於urllib.urlretrieve()所產生的快取

4.urllib.quote(url)和urllib.quote_plus(url)

將url資料獲取之後,並將其編碼,從而適用與URL字串中,使其能被列印和被web伺服器接受。

#遮蔽url中特殊的字元(包括中文),把需要編碼的字元轉化為 %xx 的形式

urllib.quote('http://www.baidu.com')

urllib.quote_plus('http://www.baidu.com')

5.urllib.unquote(url)和urllib.unquote_plus(url)

與4的函式相反

6.urllib.urlencode(query)

將URL中的鍵值對以連線符&劃分

將dict或者包含兩個元素的元組列表轉換成url引數。例如 字典{'name': 'dark-bull', 'age': 200}將被轉換為"name=dark-bull&age=200"

這裡可以與urlopen結合以實現post方法和get方法:

GET 方法:

import urllib

params=urllib.urlencode({'spam':1,'eggs':2,'bacon':0})

#params'eggs=2&bacon=0&spam=1'

f=urllib.urlopen("http://python.org/query?%s" % params)

print f.read()

import urllib

data = urllib.parse.urlencode(params).encode('utf-8')

req = urllib.request.Request(url, data)

req.add_header('Content-Type', "application/x-www-form-urlencoded")

response = urllib.request.urlopen(req)

the_page = response.read().decode('utf-8')

print(the_page)

如果不做encode,會直接報錯:POST data should be bytes or an iterable of bytes. It cannot be of type str.

如果不做decode,看到的都是assic碼

urllib模組:

 urllib.urlopen(url[,data[,proxies]])    開啟一個url的方法,返回一個檔案物件,然後可以進行類似檔案物件的操作       

 urlopen返回物件提供方法:

    read() , readline() ,readlines() , fileno() , close() :這些方法的使用方式與檔案物件完全一樣

    info():返回一個httplib.HTTPMessage物件,表示遠端伺服器返回的頭資訊

    getcode():返回Http狀態碼。如果是http請求,200請求成功完成;404網址未找到

    geturl():返回請求的url

 urllib.urlencode()    將URL中的鍵值對以連線符&劃分,暫時不支援urldecode();注意:urlencode的引數必須是Dictionary

    如:urllib.urlencode({'spam':1,'eggs':2,'bacon':0})

    結果為:eggs=2&bacon=0&spam=1

 urllib.quote(url)和urllib.quote_plus(url)    將url資料獲取之後,並將其編碼,從而適用與URL字串中,使其能被列印和被web伺服器接受

     如:

        print urllib.quote('http://www.baidu.com')

        print urllib.quote_plus('http://www.baidu.com')

     結果分別為:                      

        http%3A//www.baidu.com

        http%3A%2F%2Fwww.baidu.com

 urllib.unquote(url)和urllib.unquote_plus(url)    與上面正好相反

urllib2模組:

    直接請求一個url地址:

    urllib2.urlopen(url, data=None)    通過向指定的URL發出請求來獲取資料

    構造一個request物件資訊,然後傳送請求:

    urllib2.Request(url,data=None,header={},origin_req_host=None)    功能是構造一個請求資訊,返回的req就是一個構造好的請求

    urllib2.urlopen(url, data=None)    功能是傳送剛剛構造好的請求req,並返回一個檔案類的物件response,包括了所有的返回資訊

    response.read()    可以讀取到response裡面的html

    response.info()    可以讀到一些額外的響應頭資訊

主要區別:

urllib2可以接受一個Request類的例項來設定URL請求的headers,urllib僅可以接受URL。這意味著,你不可以通過urllib模組偽裝你的User Agent字串等(偽裝瀏覽器)。

urllib提供urle