爬蟲所需要的功能,基本上在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技術,分享一些學習的方法和需要留意的小細節