前階段使用到ftp,寫了個工具腳本http://blog.csdn.net/wklken/article/details/7059423html
最近須要抓網頁,看了下Python抓取方式python
需求:抓取網頁,解析獲取內容web
涉及庫:【重點urllib2】json
urllib http://docs.python.org/library/urllib.html瀏覽器
urllib2 http://docs.python.org/library/urllib2.html服務器
httplib http://docs.python.org/library/httplib.htmlcookie
使用urllib:app
urllib.urlopen(url[, data[, proxies]]) :socket
url: 表示遠程數據的路徑
data: 以post方式提交到url的數據
proxies:用於設置代理
urlopen返回對象提供方法:
- read() , readline() ,readlines() , fileno() , close() :這些方法的使用方式與文件對象徹底同樣
- info():返回一個httplib.HTTPMessage對象,表示遠程服務器返回的頭信息
- getcode():返回Http狀態碼。若是是http請求,200請求成功完成;404網址未找到
- geturl():返回請求的url函數
使用:
#!/usr/bin/python # -*- coding:utf-8 -*- # urllib_test.py # author:wklken # 2012-03-17 wklken#yeah.net import os import urllib url = "http://www.siteurl.com" def use_urllib(): import urllib, httplib httplib.HTTPConnection.debuglevel = 1 page = urllib.urlopen(url) print "status:", page.getcode() #200請求成功,404 print "url:", page.geturl() print "head_info:\n", page.info() print "Content len:", len(page.read())
附帶的其餘方法:(主要是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"
- urllib.pathname2url(path):將本地路徑轉換成url路徑
- urllib.url2pathname(path):將url路徑轉換成本地路徑
使用:
def urllib_other_functions(): astr = urllib.quote('this is "K"') print astr print urllib.unquote(astr) bstr = urllib.quote_plus('this is "K"') print bstr print urllib.unquote(bstr) params = {"a":"1", "b":"2"} print urllib.urlencode(params) l2u = urllib.pathname2url(r'd:\a\test.py') print l2u print urllib.url2pathname(l2u)
urlretrieve方法直接將遠程數據下載到本地
urllib.urlretrieve(url[, filename[, reporthook[, data]]]):
def callback_f(downloaded_size, block_size, romote_total_size): per = 100.0 * downloaded_size * block_size / romote_total_size if per > 100: per = 100 print "%.2f%%"% per def use_urllib_retrieve(): import urllib local = os.path.join(os.path.abspath("./"), "a.html") print local urllib.urlretrieve(url,local,callback_f)
轉載請註明出處:http://blog.csdn.net/wklken
這裏總結了一些 urllib2 的使用細節。
urllib2 默認會使用環境變量 http_proxy 來設置 HTTP Proxy。若是想在程序中明確控制 Proxy 而不受環境變量的影響,可使用:
import urllib2 enable_proxy = True proxy_handler = urllib2.ProxyHandler({"http" : 'http://some-proxy.com:8080'}) null_proxy_handler = urllib2.ProxyHandler({}) if enable_proxy: opener = urllib2.build_opener(proxy_handler) else: opener = urllib2.build_opener(null_proxy_handler) urllib2.install_opener(opener)
要加入 header,須要使用 Request 對象:這裏要注意的一個細節,使用 urllib2.install_opener() 會設置 urllib2 的全局 opener 。這樣後面的使用會很方便,但不能作更細粒度的控制,好比想在程序中使用兩個不一樣的 Proxy 設置等。比較好的作法是不使用 install_opener 去更改全局的設置,而只是直接調用 opener 的 open 方法代替全局的 urlopen 方法。
老版 Python,urllib2 的 API 並無暴露 Timeout 的設置,要設置 Timeout 值,只能更改 Socket 的全局 Timeout 值。
在 Python 2.6 之後,超時能夠經過 urllib2.urlopen() 的 timeout 參數直接設置。
import urllib2 import socket socket.setdefaulttimeout(10) # 10 秒鐘後超時 urllib2.socket.setdefaulttimeout(10) # 另外一種方式 # ---------------- import urllib2 response = urllib2.urlopen('http://www.google.com', timeout=10)
在 HTTP Request 中加入特定的 Header
import urllib2 request = urllib2.Request(uri) request.add_header('User-Agent', 'fake-client') response = urllib2.urlopen(request)
Redirect對有些 header 要特別留意,服務器會針對這些 header 作檢查:
在使用服務器提供的 RESTful 或 SOAP 服務時, Content-Type 設置錯誤會致使服務器拒絕服務
urllib2 默認狀況下會針對 HTTP 3XX 返回碼自動進行 redirect 動做,無需人工配置。要檢測是否發生了 redirect 動做,只要檢查一下 Response 的 URL 和 Request 的 URL 是否一致就能夠了。
import urllib2 response = urllib2.urlopen('http://www.google.cn') redirected = response.geturl() == 'http://www.google.cn'
若是不想自動 redirect,除了使用更低層次的 httplib 庫以外,還能夠自定義 HTTPRedirectHandler 類。
import urllib2 class RedirectHandler(urllib2.HTTPRedirectHandler): def http_error_301(self, req, fp, code, msg, headers): pass def http_error_302(self, req, fp, code, msg, headers): pass opener = urllib2.build_opener(RedirectHandler) opener.open('http://www.google.cn')
urllib2 對 Cookie 的處理也是自動的。若是須要獲得某個 Cookie 項的值,能夠這麼作:
import urllib2 import cookielib cookie = cookielib.CookieJar() opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie)) response = opener.open('http://www.google.com') for item in cookie: if item.name == 'some_cookie_item_name': print item.value
urllib2 只支持 HTTP 的 GET 和 POST 方法,若是要使用 HTTP PUT 和 DELETE ,只能使用比較低層的 httplib 庫。雖然如此,咱們仍是能經過下面的方式,使 urllib2 可以發出 PUT 或 DELETE 的請求:
import urllib2 request = urllib2.Request(uri, data=data) request.get_method = lambda: 'PUT' # or 'DELETE' response = urllib2.urlopen(request)
這種作法雖然屬於 Hack 的方式,但實際使用起來也沒什麼問題。
對於 200 OK 來講,只要使用 urlopen 返回的 response 對象的 getcode() 方法就能夠獲得 HTTP 的返回碼。但對其它返回碼來講,urlopen 會拋出異常。這時候,就要檢查異常對象的 code 屬性了:
import urllib2 try: response = urllib2.urlopen('http://restrict.web.com') except urllib2.HTTPError, e: print e.code
使用 urllib2 時,能夠經過下面的方法把 debug Log 打開,這樣收發包的內容就會在屏幕上打印出來,方便調試,有時能夠省去抓包的工做。
import urllib2 httpHandler = urllib2.HTTPHandler(debuglevel=1) httpsHandler = urllib2.HTTPSHandler(debuglevel=1) opener = urllib2.build_opener(httpHandler, httpsHandler) urllib2.install_opener(opener) response = urllib2.urlopen('http://www.google.com')