介紹一種更方便的代理池實現方案

進擊的Coder發表於2020-03-10

現在搞爬蟲,代理是不可或缺的資源。

代理池

為了保證代理的有效性,我們往往可能需要維護一個代理池。這個代理池裡面存著非常多的代理,同時代理池還會定時爬取代理來補充到代理池中,同時還會不斷檢測其中代理的有效性。當然還有一個很重要的功能就是提供一個介面,這個介面可以隨機返回代理池中的一個有效代理。

比如之前我實現過的一個代理池:,就包含了上面所說的功能,它把現在很多免費代理、付費代理整合起來,做到定時獲取,定時檢測,同時還提供了代理提取的 API。

用的時候怎麼用呢?直接請求某個介面,獲取一個隨機代理即可。比如代理池的取用地址為 ,那麼我們直接請求這個介面就能獲取一個有效代理,像這樣:

import requests
proxypool_url = ''
def get_random_proxy():    return requests.get(proxypool_url).text.strip()

在這裡我們直接呼叫 get_random_proxy 方法我們就能獲取到一個可用代理。

返回結果類似如下:

116.196.115.209:8080

然後我們再拿著這個代理去請求某些站點就行了。

情景切入

其實這樣做起來問題不大,用起來也不麻煩。但是我們必須要請求這個 API 來獲取一個代理,然後接著再去拿著這個代理去爬取站點。有沒有更最佳化的方案呢?能不能我把代理都封裝成一個 endpoint,我直接拿著這個 endpoint 來爬呢?

有的同學一聽,說:哦,這種代理我用過啊,那個 xx 雲不就這麼幹的嗎?它會給我一個代理地址,比如 xxproxy:7777,我就設定這個代理地址,然後只拿著這個代理去爬就行了,每次請求的時候 IP 都會換,具體用的那個 IP 我也不需要關心,還挺方便的。

是的就是這種,有些代理服務商就會賣這種服務的代理,叫做隧道代理(動態轉發),在這裡把某代理網的介紹複製過來。

隧道代理無須切換 IP,將 IP 切換的事情交給隧道來做,程式只需要對接一個隧道代理的固定地址即可。隧道代理(動態轉發)每一個請求一個隨機 IP。隨機 IP 來自全域性 IP 池,每天 IP 流水 50 萬以上。HTTP 隧道有併發請求限制,預設每秒只允許 5 個請求。如果需要更多請求數,請額外購買。

原理基本上就是這樣子,呼叫的時候就直接設定上這個代理就好了,比如 Scrapy 的話就是這樣呼叫:

import scrapyimport os
class MyIPSpider(scrapy.Spider):  name = 'my_ip'
 start_urls = [    ',    ',  ]
 def start_requests(self):    proxyUser = "app_id(後臺-產品管理-隧道代理頁面可查)"    proxyPass = "密碼(使用者中心-隧道代理訂單頁面可查)"    proxyHost = "http.xxxxxproxy.com"    proxyPort = "1000"
   proxyMeta = "http://%(user)s:%(pass)s@%(host)s:%(port)s" % {      "host": proxyHost,      "port": proxyPort,      "user": proxyUser,      "pass": proxyPass,    }
   for url in self.start_urls:      req = scrapy.Request(url, meta={'proxy': proxyMeta})      yield req

     def parse(self, response):        yield {          'body': response.text,        }

那麼它具體原理是什麼樣子的呢?在這裡再貼一段官方的介紹。

產品特性

隧道代理(短效版)每個 IP 的使用時長為 1 分鐘,到期後隧道將自動切換到另一個 IP。同時也允許手動切換 IP,切換間隔時間不得少於 10 秒。隧道代理有併發請求限制,預設每秒只允許 5 個請求。如果需要更多請求數,請額外購買。

產品說明

隧道代理 基於 HTTP 協議,支援 HTTP/HTTPS 協議的資料接入。•  臺在雲端維護一個全域性 IP 池 供短效代理 IP 產品使用,池中的 IP 會不間斷更新,以保證 IP 池 中有足夠多的 IP 供使用者使用。需要注意的是 IP池 中有部分 IP 可能會在當天重複出現。隧道代理(短效版) 同一時刻只能使用一個 IP,如果需要同時使用多個 IP,同一賬號需要購買多條 HTTP 隧道。

資源優勢

自有資料節點,網路穩定,速度快。百萬級別 IP 池,海量 IP 可用。毫秒級別更換 IP,響應迅速。無須頻繁更換代理伺服器地址和埠號,方便快捷。

基本上看完介紹就是這樣子,用的話就是設定一個固定代理,然後它背後有一個代理池,幫你去做轉發。也就是說它把代理池的篩選、挑選、轉發的功能都做了,這樣使用者用起來會更加方便。

但這種隧道代理也不是沒有缺點,比如:

•  不好針對性地控制針對某一站點的有效代理。比如這個隧道代理它只管給你分配一個有效能用的代理,但是它不管這個代理是不是已經被某個網站封掉了。這個問題使用代理池就能很好地解決•  這種代理一般他們會設定併發限制,比如限制每秒最多五個,多了繼續加錢。

這種代理大家可能比較好奇是怎麼實現的,其實很簡單,本節我們就來介紹下它的實現方式。

Squid

首先我們來介紹下 Squid,如果你自己搭建過代理的話,想必對 Squid 不陌生。它就是一個用來搭建 HTTP 代理的軟體。

官方介紹如下:

Squid is a caching proxy for the Web supporting HTTP, HTTPS, FTP, and more. It reduces bandwidth and improves response times by caching and reusing frequently-requested web pages. Squid has extensive access controls and makes a great server accelerator. It runs on most available operating systems, including Windows and is licensed under the GNU GPL.

官方介紹說是一個代理快取軟體,為什麼又說是快取呢?這裡先引用一張圖,其工作機制是這樣的:

介紹一種更方便的代理池實現方案

當我們客戶機透過 Squid 代理去訪問 Web頁面時,指定的代理伺服器會先檢查自己的快取,若是快取中有我們客戶機需要的頁面,那麼 Squid 伺服器將直接把快取中的頁面內容返回給客戶機,如果快取中沒有客戶端請求的頁面,那麼 Squid 代理伺服器就會向 Internet 傳送訪問請求,獲得返回的 Web 頁面後,將網頁的資料儲存到快取中併傳送給客戶機。

由於客戶機的 Web 訪問請求實際上是 Squid 代理伺服器來代替完成的,所以隱藏了使用者的真實 IP 地址,從而起到一定的保護作用。另一方面,Squid 也可以針對要訪問的目標、客戶機的地址、訪問的時間段進行過濾控制。

這就明白了吧,為什麼說是代理快取軟體,以及它為什麼能搭建一個代理伺服器。

當然 Squid 裡面可以設定透明代理、匿名代理、高匿代理等方式,都是可以配置的。當然對於爬蟲來說,選擇匿名或高匿代理是最好的。

代理設定

好了,明白了 Squid 的工作機制之後,我們其實就可以藉助於 Squid 來搭建一個代理伺服器了。比如你的公網 IP 為 x.x.x.x,然後安裝了一個 Squid,執行在 3128 埠,執行起來。

然後你就可以使用 x.x.x.x:3128 作為你的爬蟲代理了,你就擁有了一個像之前代理池中取到的某個代理一樣工作原理的代理。

當你用這個代理來爬取網站的時候,如果你設定的是高匿模式,那麼被爬取的網站識別到的 IP 就是這個伺服器的 IP,即 x.x.x.x,就偽裝成功了。

嗯,這就是 Squid 的基本使用。

但是,彷彿扯遠了,我們要說的不是這個,說的是怎樣來實現一個前文所介紹的隧道代理。

隧道代理

隧道代理的介紹前文介紹過了,那麼我們要怎麼實現呢?其實用 Squid 就可以了。

Squid 裡面有一個配置叫做 cache_peer,翻譯過來叫「快取同胞」?很奇怪的名字是吧?其實你瞭解了 Squid 的原理之後就不覺得奇怪了,前文說了,Squid 本身就是一個代理快取,即 cache,而 peer 又是同類、同胞的意思。怎麼理解呢,其實就是和自己類似的 Squid 伺服器嘛。

那麼 cache_peer 能配置什麼呢?其實就是在這裡面再配置一些類似 Squid 的代理,即 Squid 代理的代理。

其基本語法配置如下:


cache_peer hostname type http-port icp-port [options]

例如:

#                                        proxy  icp#          hostname             type     port   port  options#          -------------------- -------- ----- -----  -----------cache_peer parent.foo.net       parent    3128  3130  defaultcache_peer sib1.foo.net         sibling   3128  3130  proxy-onlycache_peer sib2.foo.net         sibling   3128  3130  proxy-onlycache_peer example.com          parent    80       0  defaultcache_peer cdn.example.com      sibling   3128     0

比如這裡就配置了 5 個 cache_peer,指定了 hostname,type,port 等等。

這樣代理就會根據對應的配置選擇特定的代理進行轉發了。

比如這裡配置了一個 default 的 cache_peer 為 parent.foo.net 的代理,那麼一旦有請求本 Squid 代理伺服器的,本 Squid 伺服器就會把請求再轉發給 parent.foo.net 這個代理伺服器,parent.foo.net 這個代理伺服器再去請求對應的網站就行了,得到響應之後再按照順序轉發回去就行了。

這就是代理的轉發,也可以理解為其中包含了兩級代理,第一級代理就是這個 Squid,第二級代理就是隨機選取的 cache_peer。

好,那麼回到原來的問題,隧道代理就有思路了吧。

我們可以把獲取下來的好多好多代理都設定成 cache_peer,Squid 會根據規則自動或隨機選擇某一代理進行請求,同時 Squid 還能同時檢測每個 cache_peer 的有效性。比如我們有一萬個代理 IP,我們寫入到 cache_peer 裡面,Squid 就會自動檢測每個代理的有效性,我們也不用再去實現檢測邏輯了。

然後如有請求來了,Squid 就會隨機選一個 cache_peer 來轉發,這樣被爬取的網站獲取的 IP 就是二級代理的 IP。

同時我們這個 Squid 的代理也不會變,就是 Squid 代理所在的伺服器地址和埠。

這樣我們就能實現一個恆定的隧道代理,同時做到請求的時候代理地址隨機動態更換了。

嗯,美滋滋。

配置實現

那麼具體配置是怎樣的呢?

這裡介紹幾個比較有用的引數:

hostname:就是二級代理伺服器的 host,不帶埠。type:型別,可以是 pareent、sibling、multicast,我們設定為 parent 就好了。port:二級代理伺服器的埠。icp port:用於查詢有關物件的鄰居快取,如果對等方不支援 ICP 或 HTCP,則設定為 0,我們設定為 0 就好。options:其他選項。在這裡其他選項也有很多配置,比較重要的有:login=user:password:如果二級代理有使用者名稱密碼,可以用 login 設定。weight=N:cache_peer 選取權重,根據 weight 來有權重地選取 cache_peer。no-query:不做查詢操作,直接獲取資料。proxy-only:指明從 peer 得到的資料不在本地快取。default:預設路由,該 peer 將被用作最後的嘗試手段。當你只有一個父代理伺服器並且其不支援 ICP 協議時,可以使用 default 和 no-query 選項讓所有請求都傳送到該父代理伺服器。round-robin:負載均衡,設定了之後會在配置的二級代理之間進行切換選取。weighted-round-robin:有權重的負載均衡,同時會根據二級代理的往返時間來改變選取權重,越快的選取機率越高。

這些是我從官方文件翻譯的,更詳細的配置大家可以去看官方文件:,裡面還介紹了其他更多引數。

好了,瞭解了上面的配置,我們的 cache_peer 應該怎麼配置呢?

這裡給一個示例:

cache_peer 58.22.22.124 parent 2053 0 no-query proxy-only weighted-round-robin login=germey:Yuy3z92hwRmJe2X6fs3BH6aWnt7xePoL

這就是一行 cache_peer 的配置。

如果有非常多的代理池,那麼可以根據這個格式來寫入一個 conf 檔案裡面,一個代理一個,Squid 引用這個檔案即可。

這個 conf 檔案可以儲存為 peers.conf,然後在 Squid 的配置檔案 squid.conf 裡面引入即可,例如:

include /etc/squid/peers.conf

這樣,Squid 的 cache peers 會被設定為有權重的負載均衡模式,當有請求來的時候,Squid 會隨機選一個 cache peer 轉發,同時 Squid 還會檢測每一個 cache peer 的有效性,我們也不用再單獨實現檢測邏輯了,省去了一大麻煩。

嗯,利用上面的方法,我就能維護一個隧道代理了,這樣一來,我就可以完成:

爬蟲的代理直接設定為該 Squid 的 host 和 port 即可。獲取到的代理直接寫入 peers.conf 配置檔案裡面,不用再去額外檢測代理有效性,Squid 會自動檢測。代理池的維護和取用和轉發由 Squid 的 cache_peer 機制自動實現,我們不用再去關心隨機選取的問題了。

OK,是不是很方便呢?這樣我們就實現了一種更方便的代理池。

高匿代理

最後再介紹下 Squid 高匿代理的關鍵配置:

request_header_access Via deny allrequest_header_access X-Forwarded-For deny all

這裡就僅做記錄了,加到 squid.conf 配置檔案即可。

最佳化方案

另外,有人說了,難道我有幾萬個 IP,每次更新都要寫入 Squid 檔案嗎?寫入之後要重啟吧,Squid 重啟的時候這個代理不就沒法用了嗎?

這個問題,一個更好的解決方案是二級代理使用 ADSL 撥號代理伺服器,peers.conf 裡面配置這些 ADSL 撥號代理,這樣 IP 的切換由 ADSL 撥號代理控制,本機 Squid 不用再動 peers.conf 配置檔案,也不用重啟了,同時還能檢測撥號代理的有效性,實現永久可用。

程式碼

在這裡提供我實現的隧道代理的原始碼,裡面還支援了代理認證的配置,打包了 Docker,感興趣可以研究一下:,謝謝!

參考來源

https://blog.51cto.com/riverxyz/1843194https://blog.51cto.com/14154700/2406060?source=dra


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31557738/viewspace-2679380/,如需轉載,請註明出處,否則將追究法律責任。

相關文章