天天看點

python 單例模式擷取IP代理python 單例模式擷取IP代理

python 單例模式擷取IP代理

tags:python python單例模式 python擷取ip代理

引言:最近在學習python,先說一下我學Python得原因,一個是因為它足夠好用,完成同樣的功能,代碼量會比其他語言少很多,有大量的豐富的庫可以使用,基本上前期根本不需要自己造什麼輪子。第二個是因為目前他很火,網上各種資料都比較豐富,且品質尚可。接下來不如正題

為什麼需要代理

提到python,雖然他能幹的事情很多,但是我們首先想起的一般都是爬蟲。爬蟲的作用是通過抓取網頁,分析并獲得網頁中的内容。像php這類語言也是可以用curl來達到爬蟲的效果,不過論爬蟲庫的數量和易用性就沒辦法和python相比了。

對網絡知識有了解的朋友應該知道,很多網站都有反爬蟲的政策,或者是針對同一ip位址頻繁請求會拒絕服務,我在剛開始寫一些東西的時候就經常因為通路的頻率太頻繁而被禁。是以說僅用自己的ip位址進行爬取是有一定的局限性的。而代理就可以解決這個問題。

代理是什麼

作為一個程式員我覺得有必要了解一些基本的網絡知識,比如說網絡代理。

我不想從哪裡複制粘貼一段介紹過來,因為我覺得那樣很low,我說說我了解的網絡代理。

如果你不了解代理,你應該知道代購吧,比如你想買一個東西,卻不想自己跑去買,可以找一個代理幫你去買。類似的,網絡代理也是在你和目的網絡之間的一個中轉方。類似如下圖

Alice->agency(代理): I want to get sth from Bob
agency(代理)->Bob: give me sth
Note right of Bob: Bob thinks
Bob-->agency(代理): there is sth!
agency(代理)-->Alice: bob give you sth
           

這裡有一個問題是,普通代理是比較好檢測出來的,有些網站不允許使用代理通路。這時候可以使用高匿代理可以解決這個問題。關于代理不多說了,有興趣的可以自己去了解。

從哪裡擷取代理

這問題就簡單了,直接百度搜尋網絡代理可以搜尋到很多免費的,免費的一般不太穩定,應付日常需求應該沒問題。如果需要穩定代理還是老老實實的花錢買付費的好一些,不要因小失大。

比如網上就經常推薦的代理

西祠代理:

http://www.xicidaili.com/nn/

本文用的快代理:

https://www.kuaidaili.com/

西祠我一開始也用了,後來因為頻繁通路被禁用過一次,幾天後才解禁,在這期間我換成了快代理并去重寫了規則每小時擷取一次代理。

代碼

本文用的python版本為3.6.5, 如果使用2.7版本的代碼需要微調

User-Agent

用來模拟不同的浏覽器,直接複制就可以了,我的檔案名為user_agents.py

#!/usr/bin/python
# -*- coding:utf-8 -*-
'''
Created on 2018-04-27

@author: Vinter_he
'''

user_agents = [
    'Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11',
    'Opera/9.25 (Windows NT 5.1; U; en)',
    'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
    'Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.5 (like Gecko) (Kubuntu)',
    'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.12) Gecko/20070731 Ubuntu/dapper-security Firefox/1.5.0.12',
    'Lynx/2.8.5rel.1 libwww-FM/2.14 SSL-MM/1.4.1 GNUTLS/1.2.9'
    
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
    "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
    "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
    "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5",
    "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
    "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
    "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
    "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
    "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
    "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",
    "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"
]           

擷取代理代碼

#!/usr/bin/python
# -*- coding:utf-8 -*-
'''
擷取快代理ip 擷取到的為https://...格式
'''
from lxml import etree
import sys ,user_agents ,random ,requests ,time

class geKuaidailiIp:
    __instance = None
    #使用單例模式
    def __new__(cls):
        if cls.__instance == None:
            cls.__instance = object.__new__(cls)
            cls.init(cls)
        return cls.__instance

    def init(self):
        print('初始化')
        self.proxieList = []
        self.lastTime = time.time() - 3601
        self.agencyUrl = 'https://www.kuaidaili.com/free/'
        self.userAgents = user_agents.user_agents
    # 擷取user-agent
    def getUserAgent(self):
        userAgent = random.choice(self.userAgents)
        return {
            'User-Agent': userAgent
        }

    def getHtml(self,url):
        response = requests.get(url = url ,headers = self.getUserAgent(),timeout = 10).text
        # sys.exit()
        html = etree.HTML(response)
        return html
    #取一頁的分析代理ip
    def parseHtmlToGetIpList(self,url):

        #擷取代理ip位址 隻取前五頁
        html = self.getHtml(url)
        ip = html.xpath('//tr/td[@data-title = "IP"]')
        port = html.xpath('//tr/td[@data-title = "PORT"]')
        type = html.xpath('//tr/td[@data-title = "類型"]')
        return type, ip, port
    # 取五頁資料并進行拼接成一個list
    def getProxies(self):
        # 1小時擷取一次代理 否則會被禁
        if time.time() - self.lastTime > 60*60:
            self.proxieList =[]
            self.lastTime = time.time()
            #隻取前五頁,因為後面的失效的會比較多,看自己需要
            for i in range(5):
                url = self.agencyUrl+'inha/'+str(i+1)+"/"
                type,ip,port = self.parseHtmlToGetIpList(url)
                count = len(port)
                for i in range(count):
                    self.proxieList.append(type[i].text+"://"+ip[i].text+":"+port[i].text)
                time.sleep(1)
            print('擷取代理')
        return self.proxieList

    def getRandomAgencyIp(self):
        self.getProxies()
        ip = random.choice(self.proxieList)
        return ip



#初始化代理 用來進行測試用
# agency = geKuaidailiIp()
# while True:
#
#     print(agency.getRandomAgencyIp())
#     time.sleep(random.randint(4,10))
           

為什麼使用單例模式

如果你可以保證自己隻建立一個代理對象的話,其實并不是必須使用單例模式。因為很多朋友可能會把建立對象的代碼寫在循環中,導緻頻繁的擷取代理而導緻自己的ip被代理方禁了。單例模式保證在一次執行腳本過程中隻有一個對象。如果對象已經建立,則直接傳回已經建立的對象,進而控制不會頻繁的通路快代理的頁面。代碼中是一小時一次。

題外話

其實早在七八年前上學期間我就接觸過python,那時候python沒有現在那麼火,我還是在查怎麼成為一名黑客的時候查到的這是一個必修課。然而當時還是比較貪玩的,學習資料也很匮乏。是以不就久放棄了。現在在人工智能和大資料的帶動下,前幾天看統計,python已經成了排名第一的腳本語言(php是世界上最好的語言,哥哥們别噴我),是以我幾個月前開始每天抽一點業餘時間學習python。幸運的是我有三門語言基礎,學習起來還算比較輕松。如果你也是一名程式員,并且有精力也希望你能在業餘時間做點什麼學點什麼來提高自己,與大家共勉。

希望大家多評論交流,互相學習