1. <nobr id="easjo"><address id="easjo"></address></nobr>

      <track id="easjo"><source id="easjo"></source></track>
      1. 
        

      2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
      3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>
          貴州做網站公司
          貴州做網站公司~專業!靠譜!
          10年網站模板開發經驗,熟悉國內外開源網站程序,包括DEDECMS,WordPress,ZBlog,Discuz! 等網站程序,可為您提供網站建設,網站克隆,仿站,網頁設計,網站制作,網站推廣優化等服務。我們專注高端營銷型網站,企業官網,集團官網,自適應網站,手機網站,網絡營銷,網站優化,網站服務器環境搭建以及托管運維等。為客戶提供一站式網站解決方案?。?!

          輕松獲得海量穩定代理!ADSL撥號代理的搭建

          來源:互聯網轉載 時間:2024-01-29 08:14:43

          我們嘗試維護過一個代理池。代理池可以挑選出許多可用代理,但是常常其穩定性不高、響應速度慢,而且這些代理通常是公共代理,可能不止一人同時使用,其IP被封的概率很大。另外,這些代理可能有效時間比較短,雖然代理池一直在篩選,但如果沒有及時更新狀態,也有可能獲取到不可用的代理。

          如果要追求更加穩定的代理,就需要購買專有代理或者自己搭建代理服務器。但是服務器一般都是固定的IP,我們總不能搭建100個代理就用100臺服務器吧,這顯然是不現實的。

          所以,ADSL動態撥號主機就派上用場了。下面我們來了解一下ADSL撥號代理服務器的相關設置。

          一、什么是ADSL

          ADSL(Asymmetric Digital Subscriber Line,非對稱數字用戶環路),它的上行和下行帶寬不對稱,它采用頻分復用技術把普通的電話線分成了電話、上行和下行三個相對獨立的信道,從而避免了相互之間的干擾。

          ADSL通過撥號的方式上網,需要輸入ADSL賬號和密碼,每次撥號就更換一個IP。IP分布在多個A段,如果IP都能使用,則意味著IP量級可達千萬。如果我們將ADSL主機作為代理,每隔一段時間主機撥號就換一個IP,這樣可以有效防止IP被封禁。另外,主機的穩定性很好,代理響應速度很快。

          二、準備工作

          首先需要成功安裝Redis數據庫并啟動服務,另外還需要安裝requests、RedisPy、Tornado庫。

          三、購買主機

          我們先購買一臺動態撥號VPS主機,這樣的主機服務商相當多。在這里使用了云立方,官方網站:http://www.yunlifang.cn/dynamicvps.asp。

          建議選擇電信線路??梢宰孕羞x擇主機配置,主要考慮帶寬是否滿足需求。

          然后進入撥號主機的后臺,預裝一個操作系統,如下圖所示。

          推薦安裝CentOS 7系統。

          然后找到遠程管理面板-遠程連接的用戶名和密碼,也就是SSH遠程連接服務器的信息。比如我使用的IP和端口是153.36.65.214:20063,用戶名是root。命令行下輸入如下代碼:

          ssh root@153.36.65.214 -p 20063

          輸入管理密碼,就可以連接上遠程服務器了。

          進入之后,我們發現一個可用的腳本文件ppp.sh,這是撥號初始化的腳本。運行此腳本會提示輸入撥號的用戶名和密碼,然后它就開始各種撥號配置。一次配置成功,后面撥號就不需要重復輸入用戶名和密碼。

          運行ppp.sh腳本,輸入用戶名密碼等待它的配置完成,如下圖所示。

          提示成功之后就可以進行撥號了。注意,在撥號之前測試ping任何網站都是不通的,因為當前網絡還沒聯通。輸入如下撥號命令:

          adsl-start

          撥號命令成功運行,沒有報錯信息,耗時約幾秒。接下來再去ping外網就可以通了。

          如果要停止撥號,可以輸入如下指令:

          adsl-stop

          之后,可以發現又連不通網絡了,如下圖所示。

          斷線重播的命令就是二者組合起來,先執行adsl-stop,再執行adsl-start。每次撥號,ifconfig命令觀察主機的IP,發現主機的IP一直在變化,網卡名稱叫作ppp0,如下圖所示。

          接下來,我們要做兩件事:一是怎樣將主機設置為代理服務器,二是怎樣實時獲取撥號主機的IP。

          四、設置代理服務器

          在Linux下搭建HTTP代理服務器,推薦TinyProxy和Squid,配置都非常簡單。在這里我們以TinyProxy為例來講解一下怎樣搭建代理服務器。

          1. 安裝 TinyProxy

          第一步就是安裝TinyProxy軟件。在這里我使用的系統是CentOS,所以使用yum來安裝。如果是其他系統如Ubuntu,可以選擇apt-get等命令安裝。

          命令行執行yum安裝指令:

          yum install -y epel-releaseyum update -yyum install -y tinyproxy

          2. 配置 TinyProxy

          TinyProxy安裝完成之后還要配置一下才可以用作代理服務器。我們需要編輯配置文件,此文件一般的路徑是/etc/tinyproxy/tinyproxy.conf。

          可以看到一行代碼:

          Port 8888

          在這里可以設置代理的端口,端口默認是8888。

          繼續向下找到如下代碼:

          Allow 127.0.0.1

          這行代碼表示被允許連接的主機IP。如果希望連接任何主機,那就直接將這行代碼注釋即可。在這里我們選擇直接注釋,也就是任何主機都可以使用這臺主機作為代理服務器。

          修改為如下代碼:

          # Allow 127.0.0.1

          設置完成之后重啟TinyProxy即可:

          systemctl enable tinyproxy.servicesystemctl restart tinyproxy.service

          防火墻開放該端口:

          iptables -I INPUT -p tcp --dport 8888 -j ACCEPT

          當然如果想直接關閉防火墻也可以:

          systemctl stop firewalld.service

          這樣我們就完成了TinyProxy的配置。

          3. 驗證 TinyProxy

          首先,用ifconfig查看當前主機的IP。比如,當前我的主機撥號IP為112.84.118.216,在其他的主機運行測試一下。

          curl命令設置代理請求httpbin,檢測代理是否生效。

          curl -x 112.84.118.216:8888 httpbin.org/get

          運行結果如下圖所示。

          如果有正常的結果輸出,并且origin的值為代理IP的地址,就證明TinyProxy配置成功了。

          五、動態獲取IP

          現在可以執行命令讓主機動態切換IP,也在主機上搭建了代理服務器。我們只需要知道撥號后的IP就可以使用代理。

          我們考慮到,在一臺主機撥號切換IP的間隙代理是不可用的,在這撥號的幾秒時間內如果有第二臺主機頂替第一臺主機,那就可以解決撥號間隙代理無法使用的問題了。所以我們要設計的架構必須要考慮支持多主機的問題。

          假如有10臺撥號主機同時需要維護,而爬蟲需要使用這10臺主機的代理,那么在爬蟲端維護的開銷是非常大的。如果爬蟲在不同的機器上運行,那么每個爬蟲必須要獲得這10臺撥號主機的配置,這顯然是不理想的。

          為了更加方便地使用代理,我們可以像上文的代理池一樣定義一個統一的代理接口,爬蟲端只需要配置代理接口即可獲取可用代理。要搭建一個接口,就勢必需要一臺服務器,而接口的數據從哪里獲得呢,當然最理想的還是選擇數據庫。

          比如我們需要同時維護10臺撥號主機,每臺撥號主機都會定時撥號,那這樣每臺主機在某個時刻可用的代理只有一個,所以我們沒有必要存儲之前的撥號代理,因為重新撥號之后之前的代理已經不能用了,所以只需要將之前的代理更新其內容就好了。數據庫要做的就是定時對每臺主機的代理進行更新,而更新時又需要撥號主機的唯一標識,根據主機標識查出這條數據,然后將這條數據對應的代理更新。

          所以數據庫端就需要存儲一個主機標識到代理的映射關系。那么很自然地我們就會想到關系型數據庫如MySQL或者Redis的Hash存儲,只需存儲一個映射關系,不需要很多字段,而且Redis比MySQL效率更高、使用更方便,所以最終選定的存儲方式就是Redis的Hash。

          六、存儲模塊

          那么接下來我們要做可被遠程訪問的Redis數據庫,各個撥號機器只需要將各自的主機標識和當前IP和端口(也就是代理)發送給數據庫就好了。

          先定義一個操作Redis數據庫的類,示例如下:

          import redisimport random# Redis數據庫IPREDIS_HOST = 'remoteaddress'# Redis數據庫密碼, 如無則填NoneREDIS_PASSWORD = 'foobared'# Redis數據庫端口REDIS_PORT = 6379# 代理池鍵名PROXY_KEY = 'adsl'class RedisClient(object):    def __init__(self, host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD, proxy_key=PROXY_KEY):        """        初始化Redis連接        :param host: Redis 地址        :param port: Redis 端口        :param password: Redis 密碼        :param proxy_key: Redis 散列表名        """        self.db = redis.StrictRedis(host=host, port=port, password=password, decode_responses=True)        self.proxy_key = proxy_key    def set(self, name, proxy):        """        設置代理        :param name: 主機名稱        :param proxy: 代理        :return: 設置結果        """        return self.db.hset(self.proxy_key, name, proxy)    def get(self, name):        """        獲取代理        :param name: 主機名稱        :return: 代理        """        return self.db.hget(self.proxy_key, name)    def count(self):        """        獲取代理總數        :return: 代理總數        """        return self.db.hlen(self.proxy_key)    def remove(self, name):        """        刪除代理        :param name: 主機名稱        :return: 刪除結果        """        return self.db.hdel(self.proxy_key, name)    def names(self):        """        獲取主機名稱列表        :return: 獲取主機名稱列表        """        return self.db.hkeys(self.proxy_key)    def proxies(self):        """        獲取代理列表        :return: 代理列表        """        return self.db.hvals(self.proxy_key)    def random(self):        """        隨機獲取代理        :return:        """        proxies = self.proxies()        return random.choice(proxies)    def all(self):        """        獲取字典        :return:        """        return self.db.hgetall(self.proxy_key)

          這里定義了一個RedisClient類,在__init__()方法中初始化了Redis連接,其中REDIS_HOST就是遠程Redis的地址,REDIS_PASSWORD是密碼,REDIS_PORT是端口,PROXY_KEY是存儲代理的散列表的鍵名。

          接下來定義了一個set()方法,這個方法用來向散列表添加映射關系。映射是從主機標識到代理的映射,比如一臺主機的標識為adsl1,當前的代理為118.119.111.172:8888,那么散列表中就會存儲一個key為adsl1、value為118.119.111.172:8888的映射,Hash結構如下圖所示。

          如果有多臺主機,只需要向Hash中添加映射即可。

          另外,get()方法就是從散列表中取出某臺主機對應的代理。remove()方法則是從散列表中移除對應的主機的代理。還有names()、proxies()、all()方法則是分別獲取散列表中的主機列表、代理列表及所有主機代理映射。count()方法則是返回當前散列表的大小,也就是可用代理的數目。

          最后還有一個比較重要的方法random(),它隨機從散列表中取出一個可用代理,類似前面代理池的思想,確保每個代理都能被取到。

          如果要對數據庫進行操作,只需要初始化RedisClient對象,然后調用它的set()或者remove()方法,即可對散列表進行設置和刪除。

          七、撥號模塊

          接下來要做的就是撥號,并把新的IP保存到Redis散列表里。

          首先是撥號定時,它分為定時撥號和非定時撥號兩種選擇。

          • 非定時撥號,最好的方法就是向該主機發送一個信號,然后主機就啟動撥號,但這樣做的話,我們首先要搭建一個重新撥號的接口,如搭建一個Web接口,請求該接口即進行撥號,但開始撥號之后,此時主機的狀態就從在線轉為離線,而此時的Web接口也就相應失效了,撥號過程無法再連接,撥號之后接口的IP也變了,所以我們無法通過接口來方便地控制撥號過程和獲取撥號結果,下次撥號還得改變撥號請求接口,所以非定時撥號的開銷還是比較大的。
          • 定時撥號,我們只需要在撥號主機上運行定時腳本即可,每隔一段時間撥號一次,更新IP,然后將IP在Redis散列表中更新即可,非常簡單易用,另外可以適當將撥號頻率調高一點,減少短時間內IP被封的可能性。

          在這里選擇定時撥號。

          接下來就是獲取IP。獲取撥號后的IP非常簡單,只需要調用ifconfig命令,然后解析出對應網卡的IP即可。

          獲取了IP之后,我們還需要進行有效性檢測。撥號主機可以自己檢測,比如可以利用requests設置自身的代理請求外網,如果成功,那么證明代理可用,然后再修改Redis散列表,更新代理。

          需要注意,由于在撥號的間隙撥號主機是離線狀態,而此時Redis散列表中還存留了上次的代理,一旦這個代理被取用了,該代理是無法使用的。為了避免這個情況,每臺主機在撥號之前還需要將自身的代理從Redis散列表中移除。

          這樣基本的流程就理順了,我們用如下代碼實現:

          import reimport timeimport requestsfrom requests.exceptions import ConnectionError, ReadTimeoutfrom db import RedisClient# 撥號網卡ADSL_IFNAME = 'ppp0'# 測試URLTEST_URL = 'http://www.baidu.com'# 測試超時時間TEST_TIMEOUT = 20# 撥號間隔ADSL_CYCLE = 100# 撥號出錯重試間隔ADSL_ERROR_CYCLE = 5# ADSL命令ADSL_BASH = 'adsl-stop;adsl-start'# 代理運行端口PROXY_PORT = 8888# 客戶端唯一標識CLIENT_NAME = 'adsl1'class Sender():    def get_ip(self, ifname=ADSL_IFNAME):        """        獲取本機IP        :param ifname: 網卡名稱        :return:        """        (status, output) = subprocess.getstatusoutput('ifconfig')        if status == 0:            pattern = re.compile(ifname + '.*?inet.*?(d+.d+.d+.d+).*?netmask', re.S)            result = re.search(pattern, output)            if result:                ip = result.group(1)                return ip    def test_proxy(self, proxy):        """        測試代理        :param proxy: 代理        :return: 測試結果        """        try:            response = requests.get(TEST_URL, proxies={                'http': 'http://' + proxy,                'https': 'https://' + proxy            }, timeout=TEST_TIMEOUT)            if response.status_code == 200:                return True        except (ConnectionError, ReadTimeout):            return False    def remove_proxy(self):        """        移除代理        :return: None        """        self.redis = RedisClient()        self.redis.remove(CLIENT_NAME)        print('Successfully Removed Proxy')    def set_proxy(self, proxy):        """        設置代理        :param proxy: 代理        :return: None        """        self.redis = RedisClient()        if self.redis.set(CLIENT_NAME, proxy):            print('Successfully Set Proxy', proxy)    def adsl(self):        """        撥號主進程        :return: None        """        while True:            print('ADSL Start, Remove Proxy, Please wait')            self.remove_proxy()            (status, output) = subprocess.getstatusoutput(ADSL_BASH)            if status == 0:                print('ADSL Successfully')                ip = self.get_ip()                if ip:                    print('Now IP', ip)                    print('Testing Proxy, Please Wait')                    proxy = '{ip}:{port}'.format(ip=ip, port=PROXY_PORT)                    if self.test_proxy(proxy):                        print('Valid Proxy')                        self.set_proxy(proxy)                        print('Sleeping')                        time.sleep(ADSL_CYCLE)                    else:                        print('Invalid Proxy')                else:                    print('Get IP Failed, Re Dialing')                    time.sleep(ADSL_ERROR_CYCLE)            else:                print('ADSL Failed, Please Check')                time.sleep(ADSL_ERROR_CYCLE)def run():    sender = Sender()    sender.adsl()

          在這里定義了一個Sender類,它的主要作用是執行定時撥號,并將新的IP測試通過之后更新到遠程Redis散列表里。

          主方法是adsl()方法,它首先是一個無限循環,循環體內就是撥號的邏輯。

          adsl()方法首先調用了remove_proxy()方法,將遠程Redis散列表中本機對應的代理移除,避免撥號時本主機的殘留代理被取到。

          接下來利用subprocess模塊來執行撥號腳本,撥號腳本很簡單,就是stop之后再start,這里將撥號的命令直接定義成了ADSL_BASH。

          隨后程序又調用get_ip()方法,通過subprocess模塊執行獲取IP的命令ifconfig,然后根據網卡名稱獲取了當前撥號網卡的IP地址,即撥號后的IP。

          再接下來就需要測試代理有效性了。程序首先調用了test_proxy()方法,將自身的代理設置好,使用requests庫來用代理連接TEST_URL。在此TEST_URL設置為百度,如果請求成功,則證明代理有效。

          如果代理有效,再調用set_proxy()方法將Redis散列表中本機對應的代理更新,設置時需要指定本機唯一標識和本機當前代理。本機唯一標識可隨意配置,其對應的變量為CLIENT_NAME,保證各臺撥號主機不沖突即可。本機當前代理則由撥號后的新IP加端口組合而成。通過調用RedisClientset()方法,參數name為本機唯一標識,proxy為撥號后的新代理,執行之后便可以更新散列表中的本機代理了。

          建議至少配置兩臺主機,這樣在一臺主機的撥號間隙還有另一臺主機的代理可用。撥號主機的數量不限,越多越好。

          在撥號主機上執行撥號腳本,示例輸出如下圖所示。

          首先移除了代理,再進行撥號,撥號完成之后獲取新的IP,代理檢測成功之后就設置到Redis散列表中,然后等待一段時間再重新進行撥號。

          我們添加了多臺撥號主機,這樣就有多個穩定的定時更新的代理可用了。Redis散列表會實時更新各臺撥號主機的代理,如下圖所示。

          圖中所示是四臺ADSL撥號主機配置并運行后的散列表的內容,表中的代理都是可用的。

          八、接口模塊

          目前為止,我們已經成功實時更新撥號主機的代理。不過還缺少一個模塊,那就是接口模塊。像之前的代理池一樣,我們也定義一些接口來獲取代理,如random獲取隨機代理、count獲取代理個數等。

          我們選用Tornado來實現,利用Tornado的Server模塊搭建Web接口服務,示例如下:

          import jsonimport tornado.ioloopimport tornado.webfrom tornado.web import RequestHandler, Application# API端口API_PORT = 8000class MainHandler(RequestHandler):    def initialize(self, redis):        self.redis = redis    def get(self, api=''):        if not api:            links = ['random', 'proxies', 'names', 'all', 'count']            self.write('<h4>Welcome to ADSL Proxy API</h4>')            for link in links:                self.write('<a href=' + link + '>' + link + '</a><br>')        if api == 'random':            result = self.redis.random()            if result:                self.write(result)        if api == 'names':            result = self.redis.names()            if result:                self.write(json.dumps(result))        if api == 'proxies':            result = self.redis.proxies()            if result:                self.write(json.dumps(result))        if api == 'all':            result = self.redis.all()            if result:                self.write(json.dumps(result))        if api == 'count':            self.write(str(self.redis.count()))def server(redis, port=API_PORT, address=''):    application = Application([        (r'/', MainHandler, dict(redis=redis)),        (r'/(.*)', MainHandler, dict(redis=redis)),    ])    application.listen(port, address=address)    print('ADSL API Listening on', port)    tornado.ioloop.IOLoop.instance().start()

          這里定義了5個接口,random獲取隨機代理,names獲取主機列表,proxies獲取代理列表,all獲取代理映射,count獲取代理數量。

          程序啟動之后便會在API_PORT端口上運行Web服務,主頁面如下圖所示。

          訪問proxies接口可以獲得所有代理列表,如下圖所示。

          訪問random接口可以獲取隨機可用代理,如下圖所示。

          我們只需將接口部署到服務器上,即可通過Web接口獲取可用代理,獲取方式和代理池類似。

          九、本節代碼

          本節代碼地址為:https://github.com/Python3WebSpider/AdslProxy。

          十、結語

          本節介紹了ADSL撥號代理的搭建過程。通過這種代理,我們可以無限次更換IP,而且線路非常穩定,抓取效果好很多。

          崔慶才

          靜覓博客博主,《Python3網絡爬蟲開發實戰》作者

          網絡推廣與網站優化公司(網絡優化與推廣專家)作為數字營銷領域的核心服務提供方,其價值在于通過技術手段與策略規劃幫助企業提升線上曝光度、用戶轉化率及品牌影響力。這...

          在當今數字化時代,公司網站已成為企業展示形象、傳遞信息和開展業務的重要平臺。然而,對于許多公司來說,網站建設的價格是一個關鍵考量因素。本文將圍繞“公司網站建設價...

          在當今的數字化時代,企業網站已成為企業展示形象、吸引客戶和開展業務的重要平臺。然而,對于許多中小企業來說,高昂的網站建設費用可能會成為其發展的瓶頸。幸運的是,隨...

          玩游戲用windows哪個版本好?1、旗艦版最好,Windows 7旗艦版不屬于微軟公司變更土地性質的Windows 7系統系列中的終結版本,是為了變成Windows XP系統的新系統,Windows7的版本還有簡易版、家庭普通版、家庭低級版、專業版。并且旗艦版是所有Windows7系統中是最貴的(正版系統)也是功能最完善的系統。xp系統和win7哪個更流暢?xp系統和win7而言xp會更流暢,而...

          石家莊九中怎么樣 石家莊市九中怎么樣?石家莊9中在哪? 石家莊市第九中學位于石家莊市,是河北省示范性高中,石家莊市示范性初中,是一所具有良好社會聲譽的中學。石家莊市第九中學成立于1956年,由市政府投資興建?,F已發展成為一所規模大、教學一流、師資一流、設施一流的國辦完整中學。學校位于新華區九中街125號(總校區)、市莊路19號(西校區)、和平西路219號(南校區)。占地面積80.6畝(5376...

          e5300cpu參數是幾代 e5300cpu參數配置?e5300cpu參數配置? e5300cpu參數配置如下:適用類型:臺式CPUCPU系列:奔騰ECPU內核:Wolfdale核心數量:雙核心雙線程:雙核心雙線程:雙核心雙線程工作功率:65W生產工藝:45納米CPU主頻:2600MHzCPU外頻:200MHz總線頻率:800MHz一級緩存:64KB二級緩存:2MB,CPU插槽類型:LGA 7...

          TOP
          国产初高中生视频在线观看|亚洲一区中文|久久亚洲欧美国产精品|黄色网站入口免费进人
          1. <nobr id="easjo"><address id="easjo"></address></nobr>

              <track id="easjo"><source id="easjo"></source></track>
              1. 
                

              2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
              3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>