Python3爬蟲裡關於代理的設定總結
在前面我們介紹了多種請求庫,如 Requests、Urllib、Selenium 等。我們接下來首先貼近實戰,瞭解一下代理怎麼使用,為後面瞭解代理池、ADSL 撥號代理的使用打下基礎。
下面我們來梳理一下這些庫的代理的設定方法。
1. 獲取代理
在做測試之前,我們需要先獲取一個可用代理,搜尋引擎搜尋“代理”關鍵字,就可以看到有許多代理服務網站,在網站上會有很多免費代理,比如西刺:http://www.xicidaili.com/,這裡列出了很多免費代理,但是這些免費代理大多數情況下都是不好用的,所以比較靠譜的方法是購買付費代理,很多網站都有售賣,數量不用多,買一個穩定可用的即可,可以自行選購。
或者如果我們本機有相關代理軟體的話,軟體一般會在本機建立 HTTP 或 SOCKS 代理服務,直接使用此代理也可以。
在這裡我的本機安裝了一部代理軟體,它會在本地 9743 埠上建立 HTTP 代理服務,也就是代理為 127.0.0.1:9743,另外還會在 9742 埠建立 SOCKS 代理服務,也就是代理為 127.0.0.1:9742,我只要設定了這個代理就可以成功將本機 IP 切換到代理軟體連線的伺服器的 IP了。
所以本節下面的示例裡我使用上述代理來演示其設定方法,你可以自行替換成自己的可用代理,設定代理後測試的網址是:http://httpbin.org/get,訪問該站點可以得到請求的一些相關資訊,其中 origin 欄位就是客戶端的 IP,我們可以根據它來判斷代理是否設定成功,也就是是否成功偽裝了IP。
下面我們來看下各個庫的代理設定方式。
2. Urllib
首先我們以最基礎的 Urllib 為例,來看一下代理的設定方法,程式碼如下:
fromurllib.errorimportURLError fromurllib.requestimportProxyHandler,build_opener proxy='127.0.0.1:9743' proxy_handler=ProxyHandler({ 'http':'http://'+proxy,'https':'https://'+proxy }) opener=build_opener(proxy_handler) try: response=opener.open('http://httpbin.org/get') print(response.read().decode('utf-8')) exceptURLErrorase: print(e.reason)
執行結果如下:
{ "args":{},"headers":{ "Accept-Encoding":"identity","Connection":"close","Host":"httpbin.org","User-Agent":"Python-urllib/3.6" },"origin":"106.185.45.153","url":"http://httpbin.org/get" }
在這裡我們需要藉助於 ProxyHandler 設定代理,引數是字典型別,鍵名為協議型別,鍵值是代理,注意此處代理前面需要加上協議,即 http 或者 https,此處設定了 http 和 https 兩種代理,當我們請求的連結是 http 協議的時候,它會呼叫 http 代理,當請求的連結是 https 協議的時候,它會呼叫https代理,所以此處生效的代理是:http://127.0.0.1:9743。
建立完 ProxyHandler 物件之後,我們需要利用 build_opener() 方法傳入該物件來建立一個 Opener,這樣就相當於此 Opener 已經設定好代理了,接下來直接呼叫它的 open() 方法即可使用此代理訪問我們所想要的連結。
執行輸出結果是一個 Json,它有一個欄位 origin,標明瞭客戶端的 IP,此處的 IP 驗證一下,確實為代理的 IP,而並不是我們真實的 IP,所以這樣我們就成功設定好代理,並可以隱藏真實 IP 了。
如果遇到需要認證的代理,我們可以用如下的方法設定:
fromurllib.errorimportURLError fromurllib.requestimportProxyHandler,build_opener proxy='username:[email protected]:9743' proxy_handler=ProxyHandler({ 'http':'http://'+proxy,'https':'https://'+proxy }) opener=build_opener(proxy_handler) try: response=opener.open('http://httpbin.org/get') print(response.read().decode('utf-8')) exceptURLErrorase: print(e.reason)
這裡改變的只是 proxy 變數,只需要在代理前面加入代理認證的使用者名稱密碼即可,其中 username 就是使用者名稱,password 為密碼,例如 username 為foo,密碼為 bar,那麼代理就是 foo:[email protected]:9743。
如果代理是 SOCKS5 型別,那麼可以用如下方式設定代理:
importsocks importsocket fromurllibimportrequest fromurllib.errorimportURLError socks.set_default_proxy(socks.SOCKS5,'127.0.0.1',9742) socket.socket=socks.socksocket try: response=request.urlopen('http://httpbin.org/get') print(response.read().decode('utf-8')) exceptURLErrorase: print(e.reason)
此處需要一個 Socks 模組,可以通過如下命令安裝:
pip3installPySocks
本地我有一個 SOCKS5 代理,執行在 9742 埠,執行成功之後和上文 HTTP 代理輸出結果是一樣的:
{ "args":{},"url":"http://httpbin.org/get" }
結果的 origin 欄位同樣為代理的 IP,設定代理成功。
3. Requests
對於 Requests 來說,代理設定更加簡單,我們只需要傳入 proxies 引數即可。
還是以上例中的代理為例,我們來看下 Requests 的代理的設定:
importrequests proxy='127.0.0.1:9743' proxies={ 'http':'http://'+proxy,'https':'https://'+proxy,} try: response=requests.get('http://httpbin.org/get',proxies=proxies) print(response.text) exceptrequests.exceptions.ConnectionErrorase: print('Error',e.args)
執行結果:
{ "args":{},"headers":{ "Accept":"*/*","Accept-Encoding":"gzip,deflate","User-Agent":"python-requests/2.18.1" },"url":"http://httpbin.org/get" }
可以發現 Requests 的代理設定比 Urllib 簡單很多,只需要構造代理字典即可,然後通過 proxies 引數即可設定代理,不需要重新構建 Opener。
可以發現其執行結果的 origin 也是代理的 IP,證明代理已經設定成功。
如果代理需要認證,同樣在代理的前面加上使用者名稱密碼即可,代理的寫法就變成:
proxy='username:[email protected]:9743'
和 Urllib 一樣,只需要將 username 和 password 替換即可。
如果需要使用 SOCKS5 代理,則可以使用如下方式:
importrequests proxy='127.0.0.1:9742' proxies={ 'http':'socks5://'+proxy,'https':'socks5://'+proxy } try: response=requests.get('http://httpbin.org/get',e.args)
在這裡需要額外安裝一個 Socks 模組,命令如下:
pip3install"requests[socks]"
執行結果是完全相同的:
{ "args":{},"url":"http://httpbin.org/get" }
另外還有一種設定方式,和 Urllib 中的方法相同,使用 socks 模組,也需要像上文一樣安裝該庫,設定方法如下:
importrequests importsocks importsocket socks.set_default_proxy(socks.SOCKS5,9742) socket.socket=socks.socksocket try: response=requests.get('http://httpbin.org/get') print(response.text) exceptrequests.exceptions.ConnectionErrorase: print('Error',e.args)
這樣也可以設定 SOCKS5 代理,執行結果完全相同,相比第一種方法,此方法是全域性設定,不同情況可以選用不同的方法。
4. Selenium
Selenium 同樣也可以設定代理,在這裡分兩種介紹,一個是有介面瀏覽器,以 Chrome 為例介紹,另一種是無介面瀏覽器,以 PhantomJS 為例介紹。
Chrome
對於 Chrome 來說,用 Selenium 設定代理的方法也非常簡單,設定方法如下:
fromseleniumimportwebdriver proxy='127.0.0.1:9743' chrome_options=webdriver.ChromeOptions() chrome_options.add_argument('--proxy-server=http://'+proxy) browser=webdriver.Chrome(chrome_options=chrome_options) browser.get('http://httpbin.org/get')
在這裡我們通過 ChromeOptions 來設定代理,在建立 Chrome 物件的時候通過 chrome_options 引數傳遞即可。
這樣在執行之後便會彈出一個 Chrome 瀏覽器,訪問目標連結之後輸出結果如下:
{ "args":{},"headers":{ "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8","Accept-Language":"zh-CN,zh;q=0.8","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0(Macintosh;IntelMacOSX10_12_3)AppleWebKit/537.36(KHTML,likeGecko) Chrome/59.0.3071.115Safari/537.36" },"url":"http://httpbin.org/get" }
可以看到 origin 同樣為代理 IP 的地址,代理設定成功。
如果代理是認證代理,則設定方法相對比較麻煩,方法如下:
fromseleniumimportwebdriver fromselenium.webdriver.chrome.optionsimportOptions importzipfile ip='127.0.0.1' port=9743 username='foo' password='bar' manifest_json=""" { "version":"1.0.0","manifest_version":2,"name":"ChromeProxy","permissions":[ "proxy","tabs","unlimitedStorage","storage","<all_urls>","webRequest","webRequestBlocking" ],"background":{ "scripts":["background.js"] } } """ background_js=""" varconfig={ mode:"fixed_servers",rules:{ singleProxy:{ scheme:"http",host:"%(ip)s",port:%(port)s } } } chrome.proxy.settings.set({value:config,scope:"regular"},function(){}); functioncallbackFn(details){ return{ authCredentials:{ username:"%(username)s",password:"%(password)s" } } } chrome.webRequest.onAuthRequired.addListener( callbackFn,{urls:["<all_urls>"]},['blocking'] ) """%{'ip':ip,'port':port,'username':username,'password':password} plugin_file='proxy_auth_plugin.zip' withzipfile.ZipFile(plugin_file,'w')aszp: zp.writestr("manifest.json",manifest_json) zp.writestr("background.js",background_js) chrome_options=Options() chrome_options.add_argument("--start-maximized") chrome_options.add_extension(plugin_file) browser=webdriver.Chrome(chrome_options=chrome_options) browser.get('http://httpbin.org/get')
在這裡需要在本地建立一個 manifest.json 配置檔案和 background.js 指令碼來設定認證代理,執行之後本地會生成一個 proxy_auth_plugin.zip 檔案儲存配置。
執行結果和上例一致,origin 同樣為代理 IP。
PhantomJS
對於 PhantomJS,代理設定方法可以藉助於 service_args 引數,也就是命令列引數,代理設定方法如下:
fromseleniumimportwebdriver service_args=[ '--proxy=127.0.0.1:9743','--proxy-type=http' ] browser=webdriver.PhantomJS(service_args=service_args) browser.get('http://httpbin.org/get') print(browser.page_source)
在這裡我們只需要使用 service_args 引數,將命令列的一些引數定義為列表,在初始化的時候傳遞即可。
執行結果:
{ "args":{},en,*","User-Agent":"Mozilla/5.0(Macintosh;IntelMacOSX)AppleWebKit/538.1(KHTML,likeGecko) PhantomJS/2.1.0 Safari/538.1" },"url":"http://httpbin.org/get" }
執行結果的 origin 同樣為代理的 IP,設定代理成功。
如果需要認證,那麼只需要再加入 –proxy-auth 選項即可,這樣引數就改為:
service_args=[ '--proxy=127.0.0.1:9743','--proxy-type=http','--proxy-auth=username:password' ]
將 username 和 password 替換為認證所需的使用者名稱和密碼即可。
5. 本節程式碼
本節程式碼地址為:https://github.com/Python3WebSpider/ProxySettings。
6. 結語
本節介紹了前文所介紹的請求庫的代理設定方法,稍作了解即可,後面我們會使用這些方法來搭建代理池和爬取網站,進一步加深印象。