python爬蟲開發之urllib模塊詳細使用方法與實例全解

爬蟲所需要的功能,基本上在urllib中都能找到,學習這個標準庫,可以更加深入的理解後面更加便利的requests庫。

首先

在Pytho2.x中使用import urllib2——-對應的,在Python3.x中會使用import urllib.request,urllib.error

在Pytho2.x中使用import urllib——-對應的,在Python3.x中會使用import urllib.request,urllib.error,urllib.parse

在Pytho2.x中使用import urlparse——-對應的,在Python3.x中會使用import urllib.parse

在Pytho2.x中使用import urlopen——-對應的,在Python3.x中會使用import urllib.request.urlopen

在Pytho2.x中使用import urlencode——-對應的,在Python3.x中會使用import urllib.parse.urlencode

在Pytho2.x中使用import urllib.quote——-對應的,在Python3.x中會使用import urllib.request.quote

在Pytho2.x中使用cookielib.CookieJar——-對應的,在Python3.x中會使用http.CookieJar

在Pytho2.x中使用urllib2.Request——-對應的,在Python3.x中會使用urllib.request.Request

urllib是Python自帶的標準庫,無需安裝,直接可以用。

urllib模塊提供瞭如下功能:

網頁請求(urllib.request)
URL解析(urllib.parse)
代理和cookie設置
異常處理(urllib.error)
robots.txt解析模塊(urllib.robotparser)
urllib包中urllib.request模塊
1、urllib.request.urlopen
urlopen一般常用的有三個參數,它的參數如下:

r = urllib.requeset.urlopen(url,data,timeout)

url:鏈接格式:協議://主機名:[端口]/路徑

data:附加參數 必須是字節流編碼格式的內容(bytes類型),可通過bytes()函數轉化,如果要傳遞這個參數,請求方式就不再是GET方式請求,而是POST方式

timeout: 超時 單位爲秒
get請求

import urllib
r = urllib.urlopen('//www.jb51.net/')
datatLine = r.readline() #讀取html頁面的第一行
data=file.read() #讀取全部
f=open("./1.html","wb") # 網頁保存在本地
f.write(data)
f.close()

rlopen返回對象提供方法:

read() , readline() ,readlines() , fileno() , close() :這些方法的使用方式與文件對象完全一樣 info():返回一個httplib.HTTPMessage對象,表示遠程服務器返回的頭信息 getcode():返回Http狀態碼。如果是http請求,200請求成功完成;404網址未找到 geturl():返回請求的url

urllib.quote(url)和urllib.quote_plus(url),對關鍵字進行編碼可使得urlopen能夠識別

POST請求

import urllib.request
import urllib.parse
url = 'https://passport.jb51.net/user/signin?'
post = {
'username': 'xxx',
'password': 'xxxx'
}
postdata = urllib.parse.urlencode(post).encode('utf-8')
req = urllib.request.Request(url, postdata)
r = urllib.request.urlopen(req)

我們在進行註冊、登錄等操作時,會通過POST表單傳遞信息

這時,我們需要分析頁面結構,構建表單數據post,使用urlencode()進行編碼處理,返回字符串,再指定’utf-8’的編碼格式,這是因爲POSTdata只能是bytes或者file object。最後通過Request()對象傳遞postdata,使用urlopen()發送請求。

2、urllib.request.Request
urlopen()方法可以實現最基本請求的發起,但這幾個簡單的參數並不足以 構建一個完整的請求,如果請求中需要加入headers(請求頭)等信息模擬瀏覽器,我們就可以利用更強大的Request類來構建一個請求。

import urllib.request
import urllib.parse
url = 'https://passport.jb51.net/user/signin?'
post = {
'username': 'xxx',
'password': 'xxxx'
}
postdata = urllib.parse.urlencode(post).encode('utf-8')
req = urllib.request.Request(url, postdata)
r = urllib.request.urlopen(req)

3、urllib.request.BaseHandler
在上面的過程中,我們雖然可以構造Request ,但是一些更高級的操作,比如 Cookies處理,代理該怎樣來設置?

接下來就需要更強大的工具 Handler 登場了 基本的urlopen()函數不支持驗證、cookie、代理或其他HTTP高級功能。要支持這些功能,必須使用build_opener()函數來創建自己的自定義opener對象。

首先介紹下 urllib.request.BaseHandler ,它是所有其他 Handler 的父類,它提供了最基本的 Handler 的方法。

HTTPDefaultErrorHandler 用於處理HTTP響應錯誤,錯誤都會拋出 HTTPError 類型的異常。

HTTPRedirectHandler 用於處理重定向

HTTPCookieProcessor 用於處理 Cookie 。

ProxyHandler 用於設置代理,默認代理爲空。

HTTPPasswordMgr用於管理密碼,它維護了用戶名密碼的表。

HTTPBasicAuthHandler 用於管理認證,如果一個鏈接打開時需要認證,那麼可以用它來解決認證問題。
代理服務器設置

def use_proxy(proxy_addr,url):
import urllib.request
#構建代理
proxy=urllib.request.ProxyHandler({'http':proxy_addr})
# 構建opener對象
opener=urllib.request.build_opener(proxy,urllib.request.HTTPHandler)
# 安裝到全局
# urllib.request.install_opener(opener)
# data=urllib.request.urlopen(url).read().decode('utf8') 以全局方式打開
data=opener.open(url) # 直接用句柄方式打開
return data
proxy_addr='61.163.39.70:9999'
data=use_proxy(proxy_addr,'//www.jb51.net')
print(len(data))
## 異常處理以及日輸出

opener通常是build_opener()創建的opener對象。

install_opener(opener) 安裝opener作爲urlopen()使用的全局URL opener

cookie的使用
獲取Cookie保存到變量

import http.cookiejar, urllib.request
#使用http.cookiejar.CookieJar()創建CookieJar對象
cookie = http.cookiejar.CookieJar()
handler = urllib.request.HTTPCookieProcessor(cookie)
#使用HTTPCookieProcessor創建cookie處理器,並以其爲參數構建opener對象
opener = urllib.request.build_opener(handler)
#將opener安裝爲全局
urllib.request.install_opener(opener)
response = urllib.request.urlopen('//www.jb51.net')
#response = opener.open('//www.jb51.net')
for item in cookie:
print 'Name = '+item.name
print 'Value = '+item.value

首先我們必須聲明一個 CookieJar 對象,接下來我們就需要利用 HTTPCookieProcessor 來構建一個 handler ,最後利用 build_opener 方法構建出 opener ,執行 open() 即可。 最後循環輸出cookiejar

獲取Cookie保存到本地

import cookielib
import urllib
#設置保存cookie的文件,同級目錄下的cookie.txt
filename = 'cookie.txt'
#聲明一個MozillaCookieJar對象實例來保存cookie,之後寫入文件
cookie = cookielib.MozillaCookieJar(filename)
#利用urllib庫的HTTPCookieProcessor對象來創建cookie處理器
handler = urllib.request.HTTPCookieProcessor(cookie)
#通過handler來構建opener
opener = urllib.request.build_opener(handler)
#創建一個請求,原理同urllib2的urlopen
response = opener.open("//www.jb51.net")
#保存cookie到文件
cookie.save(ignore_discard=True, ignore_expires=True)

異常處理
異常處理結構如下

try:
# 要執行的代碼
print(...)
except:
#try代碼塊裏的代碼如果拋出異常了,該執行什麼內容
print(...)
else:
#try代碼塊裏的代碼如果沒有跑出異常,就執行這裏
print(...)
finally:
#不管如何,finally裏的代碼,是總會執行的
print(...)

URLerror產生原因:

1、網絡未連接(即不能上網)

from urllib import request, error
try:
r=request.urlopen('//www.jb51.net')
except error.URLError as e:
print(e.reason)

2、訪問頁面不存(HTTPError)

客戶端向服務器發送請求,如果成功地獲得請求的資源,則返回的狀態碼爲200,表示響應成功。如果請求的資源不存在, 則通常返回404錯誤。

from urllib imort request, error
try:
response = request.urlopen('//www.jb51.net')
except error.HTTPError as e:
print(e.reason, e.code, e.headers, sep='\n')
else:
print("Request Successfully')
# 加入 hasattr屬性提前對屬性,進行判斷原因
from urllib import request,error
try:
response=request.urlopen('http://blog.jb51.net')
except error.HTTPError as e:
if hasattr(e,'code'):
print('the server couldn\'t fulfill the request')
print('Error code:',e.code)
elif hasattr(e,'reason'):
print('we failed to reach a server')
print('Reason:',e.reason)
else:
print('no exception was raised')
# everything is ok

下面爲大家列出幾個urllib模塊很有代表性的實例
1、引入urllib模塊

import urllib.request
response = urllib.request.urlopen('http://jb51.net/')
html = response.read()

2、使用 Request

import urllib.request
req = urllib.request.Request('http://jb51.net/')
response = urllib.request.urlopen(req)
the_page = response.read()

3、發送數據

#! /usr/bin/env python3
import urllib.parse
import urllib.request
url = 'http://localhost/login.php'
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
values = {
'act' : 'login',
'login[email]' : '[email protected]',
'login[password]' : '123456'
}
data = urllib.parse.urlencode(values)
req = urllib.request.Request(url, data)
req.add_header('Referer', '//www.jb51.net/')
response = urllib.request.urlopen(req)
the_page = response.read()
print(the_page.decode("utf8"))

4、發送數據和header

#! /usr/bin/env python3
import urllib.parse
import urllib.request
url = 'http://localhost/login.php'
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
values = {
'act' : 'login',
'login[email]' : '[email protected]',
'login[password]' : '123456'
}
headers = { 'User-Agent' : user_agent }
data = urllib.parse.urlencode(values)
req = urllib.request.Request(url, data, headers)
response = urllib.request.urlopen(req)
the_page = response.read()
print(the_page.decode("utf8"))

5、http 錯誤

#! /usr/bin/env python3
import urllib.request
req = urllib.request.Request('//www.jb51.net ')
try:
urllib.request.urlopen(req)
except urllib.error.HTTPError as e:
print(e.code)
print(e.read().decode("utf8"))

6、異常處理

#! /usr/bin/env python3
from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError
req = Request("//www.jb51.net /")
try:
response = urlopen(req)
except HTTPError as e:
print('The server couldn't fulfill the request.')
print('Error code: ', e.code)
except URLError as e:
print('We failed to reach a server.')
print('Reason: ', e.reason)
else:
print("good!")
print(response.read().decode("utf8"))

7、異常處理

from urllib.request import Request, urlopen
from urllib.error import URLError
req = Request("//www.jb51.net /")
try:
response = urlopen(req)
except URLError as e:
if hasattr(e, 'reason'):
print('We failed to reach a server.')
print('Reason: ', e.reason)
elif hasattr(e, 'code'):
print('The server couldn't fulfill the request.')
print('Error code: ', e.code)
else:
print("good!")
print(response.read().decode("utf8"))

8、HTTP 認證

#! /usr/bin/env python3
import urllib.request
# create a password manager
password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
# Add the username and password.
# If we knew the realm, we could use it instead of None.
top_level_url = "https://www.jb51.net /"
password_mgr.add_password(None, top_level_url, 'rekfan', 'xxxxxx')
handler = urllib.request.HTTPBasicAuthHandler(password_mgr)
# create "opener" (OpenerDirector instance)
opener = urllib.request.build_opener(handler)
# use the opener to fetch a URL
a_url = "https://www.jb51.net /"
x = opener.open(a_url)
print(x.read())
# Install the opener.
# Now all calls to urllib.request.urlopen use our opener.
urllib.request.install_opener(opener)
a = urllib.request.urlopen(a_url).read().decode('utf8')
print(a)

9、使用代理

#! /usr/bin/env python3
import urllib.request
proxy_support = urllib.request.ProxyHandler({'sock5': 'localhost:1080'})
opener = urllib.request.build_opener(proxy_support)
urllib.request.install_opener(opener)
a = urllib.request.urlopen("//www.jb51.net ").read().decode("utf8")
print(a)

10、超時

#! /usr/bin/env python3
import socket
import urllib.request
# timeout in seconds
timeout = 2
socket.setdefaulttimeout(timeout)
# this call to urllib.request.urlopen now uses the default timeout
# we have set in the socket module
req = urllib.request.Request('//www.jb51.net /')
a = urllib.request.urlopen(req).read()
print(a)

11.自己創建build_opener

header=[('User-Agent','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36')]
#創建opener對象
opener=urllib.request.build_opener()
opener.addheaders=header
#設置opener對象作爲urlopen()使用的全局opener
urllib.request.install_opener(opener)
response =urllib.request.urlopen('//www.jb51.net/')
buff = response.read()
html = buff .decode("utf8")
response.close()
print(the_page)

12.urlib.resquest.urlretrieve遠程下載

header=[('User-Agent','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36')]
#創建opener對象
opener=urllib.request.build_opener()
opener.addheaders=header
#設置opener對象作爲urlopen()使用的全局opener
urllib.request.install_opener(opener)
#下載文件到當前文件夾
urllib.request.urlretrieve('//www.jb51.net/','baidu.html')
#清除urlretrieve產生的緩存
urlib.resquest.urlcleanup()

13.post請求

import urllib.request
import urllib.parse
url='//www.jb51.net/mypost/'
#將數據使用urlencode編碼處理後,使用encode()設置爲utf-8編碼
postdata=urllib.parse.urlencode({name:'測試名',pass:"123456"}).encode('utf-8')
#urllib.request.quote()接受字符串,
#urllib.parse.urlencode()接受字典或者列表中的二元組[(a,b),(c,d)],將URL中的鍵值對以連接符&劃分
req=urllib.request.Request(url,postdata)
#urllib.request.Request(url, data=None, header={}, origin_req_host=None, unverifiable=False, #method=None)
#url:包含URL的字符串。
#data:http request中使用,如果指定,則發送POST而不是GET請求。
#header:是一個字典。
#後兩個參數與第三方cookie有關。
req.add_header('user-agent','User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/
537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0')
data=urllib.request.urlopen(req).read()
//urlopen()的data參數默認爲None,當data參數不爲空的時候,urlopen()提交方式爲Post。

14.cookie的使用
1.獲取Cookie保存到變量

import urllib.request
import http.cookie
# 聲明一個CookieJar對象實例來保存cookie
cookie = cookielib.CookieJar()
# 利用urllib庫的HTTPCookieProcessor對象來創建cookie處理器
handler = urllib.request.HTTPCookieProcessor(cookie)
# 通過handler來構建opener
opener = urllib.request.build_opener(handler)
# 此處的open方法同urllib.request的urlopen方法,也可以傳入request
urllib.request.install_opener(opener)
#使用opener或者urlretrieve方法來獲取需要的網站cookie
urllib.request.urlretrieve('//www.jb51.net/','baidu.html')
# data=urllib.request.urlopen('//www.jb51.net/')

2.保存cookies到文件

import http.cookie
import urllib.request
# 設置保存cookie的文件,同級目錄下的cookie.txt
filename = 'cookie.txt'
# 聲明一個MozillaCookieJar對象實例來保存cookie,之後寫入文件
cookie = http.cookie.MozillaCookieJar(filename)
# 利用urllib庫的HTTPCookieProcessor對象來創建cookie處理器
handler = urllib.request.HTTPCookieProcessor(cookie)
# 通過handler來構建opener
opener = urllib.request.build_opener(handler)
# 創建一個請求,原理同urllib的urlopen
response = opener.open("//www.jb51.net")
# 保存cookie到文件
cookie.save(ignore_discard=True, ignore_expires=True)

3.從文件中獲取cookies並訪問

import http.cookielib
import urllib.request
# 創建MozillaCookieJar實例對象
cookie = http.cookie.MozillaCookieJar()
# 從文件中讀取cookie內容到變量
cookie.load('cookie.txt', ignore_discard=True, ignore_expires=True)
# 創建請求的request
req = urllib.Request("//www.jb51.net")
# 利用urllib的build_opener方法創建一個opener
opener = urllib.build_opener(urllib.request.HTTPCookieProcessor(cookie))
response = opener.open(req)
print (response.read())

15.代理服務器設置

import socket
#設置Socket連接超時時間,同時決定了urlopen的超時時間
socket.setdefaulttimeout(1)
import urllib.request
#代理服務器信息,http代理使用地址
startime = time.time()
#設置http和https代理
proxy=request.ProxyHandler({'https':'175.155.25.91:808','http':'175.155.25.91:808'})
opener=request.build_opener(proxy)
opener.addheaders=[('User-Agent','Mozilla/5.0 (Windows NT 10.0; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0'),
# ("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"),
# ("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3"),
# ("Accept-Encoding","gzip, deflate, br"),
# ("Connection","keep-alive"),
# ("Pragma","no-cache"),
# ("Cache-Control","no-cache")
  ]
request.install_opener(opener)
# data = request.urlopen('https://www.jb51.net/find-ip-address').read()
data = request.urlopen( 'http://www.ipip.net/' ).read().decode('utf-8')
# data=gzip.decompress(data).decode('utf-8','ignore')
endtime = time.time()
delay = endtime-startime
print(data)

有時在urlopen的data數據直接decode(‘utf-8’)會失敗,必須要使用gzip.decompress(‘utf-8’,‘ignore’)才能打開,猜測應該是header的問題,換一個有時會好

最後給大家推薦一個口碑不錯的python聚集地【點擊進入】,這裏有很多的老前輩學習技巧,學習心得

,面試技巧,職場經歷等分享,更爲大家精心準備了零基礎入門資料,實戰項目資料,每天都有程序員

定時講解Python技術,分享一些學習的方法和需要留意的小細節

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章