導讀 | urllib 模塊作為Python 3 處理 URL 的組件集合,如果你有 Python 2 的知識,那么你就會注意到 Python 2 中有 urllib 和 urllib2 兩個版本的模塊,這些現在都是 Python 3 的 urllib 包的一部分,具體如何來體現它們之間的關系 |
Python 3 的 urllib 模塊是一堆可以處理 URL 的組件集合。如果你有 Python 2 的知識,那么你就會注意到 Python 2 中有 urllib 和 urllib2 兩個版本的模塊。這些現在都是 Python 3 的 urllib 包的一部分。當前版本的 urllib 包括下面幾部分:
- urllib.request
- urllib.error
- urllib.parse
- urllib.rebotparser
接下來我們會分開討論除了 urllib.error 以外的幾部分。官方文檔實際推薦你嘗試第三方庫, requests,一個高 級的 HTTP 客戶端接口。然而我依然認為知道如何不依賴第三方庫打開 URL 并與之進行交互是很有用的,而且這也可以幫助你理解為什么 requests 包是如此的流行。
urllib.requesturllib.request 模塊期初是用來打開和獲取 URL 的。讓我們看看你可以用函數 urlopen 可以做的事:
>>>importurllib.request >>>url=urllib.request.urlopen(') >>>url.geturl() ' >>>url.info() <http.client.HTTPMessageobjectat0x7fddc2de04e0> >>>header=url.info() >>>header.as_string() ('Date:Fri,24Jun201618:21:19GMT/n' 'Expires:-1/n' 'Cache-Control:private,max-age=0/n' 'Content-Type:text/html;charset=ISO-8859-1/n' 'P3P:CP="ThisisnotaP3Ppolicy!See' ' 'Server:gws/n' 'X-XSS-Protection:1;mode=block/n' 'X-Frame-Options:SAMEORIGIN/n' 'Set-Cookie:' 'NID=80=tYjmy0JY6flsSVj7DPSSZNOuqdvqKfKHDcHsPIGu3xFv41LvH_Jg6LrUsDgkPrtM2hmZ3j9V76pS4K_cBg7pdwueMQfr0DFzw33SwpGex5qzLkXUvUVPfe9g699Qz4cx9ipcbU3HKwrRYA;' 'expires=Sat,24-Dec-201618:21:19GMT;path=/;domain=.google.com;HttpOnly/n' 'Alternate-Protocol:443:quic/n' 'Alt-Svc:quic=":443";ma=2592000;v="34,33,32,31,30,29,28,27,26,25"/n' 'Accept-Ranges:none/n' 'Vary:Accept-Encoding/n' 'Connection:close/n' '/n') >>>url.getcode() 200
在這里我們包含了需要的模塊,然后告訴它打開 Google 的 URL。現在我們就有了一個可以交互的 HTTPResponse 對象。我們要做的第一件事是調用方法 geturl ,它會返回根據 URL 獲取的資源。這可以讓我們發現 URL 是否進行了重定向。
接下來調用 info ,它會返回網頁的元數據,比如請求頭信息。因此,我們可以將結果賦給我們的 headers 變量,然后調用它的方法 as_string 。就可以打印出我們從 Google 收到的頭信息。你也可以通過 getcode 得到網頁的 HTTP 響應碼,當前情況下就是 200,意思是正常工作。
如果你想看看網頁的 HTML 代碼,你可以調用變量 url 的方法 read。我不準備再現這個過程,因為輸出結果太長了。
請注意 request 對象默認發起 GET 請求,除非你指定了它的 data 參數。如果你給它傳遞了 data 參數,這樣 request 對象將會變成 POST 請求。
下載文件urllib 一個典型的應用場景是下載文件。讓我們看看幾種可以完成這個任務的方法:
>>>importurllib.request >>>url='http://www.blog.pythonlibrary.org/wp-content/uploads/2012/06/wxDbViewer.zip' >>>response=urllib.request.urlopen(url) >>>data=response.read() >>>withopen('/home/mike/Desktop/test.zip','wb')asfobj: ...fobj.write(data) ...
這個例子中我們打開一個保存在我的博客上的 zip 壓縮文件的 URL。然后我們讀出數據并將數據寫到磁盤。一個替代此操作的方案是使用 urlretrieve :
>>>importurllib.request >>>url='http://www.blog.pythonlibrary.org/wp-content/uploads/2012/06/wxDbViewer.zip' >>>tmp_file,header=urllib.request.urlretrieve(url) >>>withopen('/home/mike/Desktop/test.zip','wb')asfobj: ...withopen(tmp_file,'rb')astmp: ...fobj.write(tmp.read())
方法 urlretrieve 會把網絡對象拷貝到本地文件。除非你在使用 urlretrieve 的第二個參數指定你要保存文件的路徑,否則這個文件將被拷貝到臨時文件夾的隨機命名的一個文件中。這個可以為你節省一步操作,并且使代碼看起來更簡單:
>>>importurllib.request >>>url='http://www.blog.pythonlibrary.org/wp-content/uploads/2012/06/wxDbViewer.zip' >>>urllib.request.urlretrieve(url,'/home/mike/Desktop/blog.zip') ('/home/mike/Desktop/blog.zip', <http.client.HTTPMessageobjectat0x7fddc21c2470>)
如你所見,它返回了文件保存的路徑,以及從請求得來的頭信息。
設置你的用戶代理當你使用瀏覽器訪問網頁時,瀏覽器會告訴網站它是誰。這就是所謂的 user-agent (用戶代理)字段。Python 的 urllib 會表示它自己為 Python-urllib/x.y , 其中 x 和 y 是你使用的 Python 的主、次版本號。有一些網站不認識這個用戶代理字段,然后網站可能會有奇怪的表現或者根本不能正常工作。辛運的是你可以很輕松的設置你自己的 user-agent 字段。
>>>importurllib.request >>>user_agent='Mozilla/5.0(X11;Ubuntu;Linuxx86_64;rv:47.0)Gecko/20100101Firefox/47.0' >>>url=' >>>headers={'User-Agent':user_agent} >>>request=urllib.request.Request(url,headers=headers) >>>withurllib.request.urlopen(request)asresponse: ...withopen('/home/mdriscoll/Desktop/user_agent.html','wb')asout: ...out.write(response.read())
這里設置我們的用戶代理為 Mozilla FireFox ,然后我們訪問 , 它會告訴我們它識別出的我們的 user-agent 字段。之后我們將 url 和我們的頭信息傳給 urlopen 創建一個 Request 實例。最后我們保存這個結果。如果你打開這個結果,你會看到我們成功的修改了自己的 user-agent 字段。使用這段代碼盡情的嘗試不同的值來看看它是如何改變的。
urllib.parseurllib.parse 庫是用來拆分和組合 URL 字符串的標準接口。比如,你可以使用它來轉換一個相對的 URL 為絕對的 URL。讓我們試試用它來轉換一個包含查詢的 URL :
>>>fromurllib.parseimporturlparse >>>result=urlparse(') >>>result ParseResult(scheme='https',netloc='duckduckgo.com',path='/',params='',query='q=python+stubbing&t=canonical&ia=qa',fragment='') >>>result.netloc 'duckduckgo.com' >>>result.geturl() ' >>>result.port None
這里我們導入了函數 urlparse , 并且把一個包含搜索查詢字串的 duckduckgo 的 URL 作為參數傳給它。我的查詢字串是搜索關于 “python stubbing” 的文章。如你所見,它返回了一個 ParseResult 對象,你可以用這個對象了解更多關于 URL 的信息。舉個例子,你可以獲取到端口信息(本例中沒有端口信息)、網絡位置、路徑和很多其它東西。
提交一個 Web 表單這個模塊還有一個方法 urlencode 可以向 URL 傳輸數據。 urllib.parse 的一個典型使用場景是提交 Web 表單。讓我們通過搜索引擎 duckduckgo 搜索 Python 來看看這個功能是怎么工作的。
>>>importurllib.request >>>importurllib.parse >>>data=urllib.parse.urlencode({'q':'Python'}) >>>data 'q=Python' >>>url=' >>>full_url=url+'?'+data >>>response=urllib.request.urlopen(full_url) >>>withopen('/home/mike/Desktop/results.html','wb')asf: ...f.write(response.read())
這個例子很直接。基本上我們是使用 Python 而不是瀏覽器向 duckduckgo 提交了一個查詢。要完成這個我們需要使用 urlencode 構建我們的查詢字符串。然后我們把這個字符串和網址拼接成一個完整的正確 URL ,然后使用 urllib.request 提交這個表單。最后我們就獲取到了結果然后保存到磁盤上。
urllib.robotparserrobotparser 模塊是由一個單獨的類 RobotFileParser 構成的。這個類會回答諸如一個特定的用戶代理是否獲取已經設置了 robot.txt 的網站的 URL。 robot.txt 文件會告訴網絡爬蟲或者機器人當前網站的那些部分是不允許被訪問的。讓我們看一個簡單的例子:
>>>importurllib.robotparser >>>robot=urllib.robotparser.RobotFileParser() >>>robot.set_url(') None >>>robot.read() None >>>robot.can_fetch('*',') True >>>robot.can_fetch('*',') False
這里我們導入了 robot 分析器類,然后創建一個實例。然后我們給它傳遞一個表明網站 robots.txt 位置的 URL 。接下來我們告訴分析器來讀取這個文件。完成后,我們給它了一組不同的 URL 讓它找出那些我們可以爬取而那些不能爬取。我們很快就看到我們可以訪問主站但是不能訪問 cgi-bin 路徑。
總結一下現在你就有能力使用 Python 的 urllib 包了。在這一節里,我們學習了如何下載文件、提交 Web 表單、修改自己的用戶代理以及訪問 robots.txt。 urllib 還有一大堆附加功能沒有在這里提及,比如網站身份認證。你可能會考慮在使用 urllib 進行身份認證之前切換到 requests 庫,因為 requests 已經以更易用和易調試的方式實現了這些功能。我同時也希望提醒你 Python 已經通過 http.cookies 模塊支持 Cookies 了,雖然在 request 包里也很好的封裝了這個功能。你應該可能考慮同時試試兩個來決定那個最適合你。
原文來自: