python 代理池

#coding=utf-8
import requests
import re
import Queue
import MySQLdb
import gevent
from gevent.threadpool import ThreadPool

#def conn_sql():
    #conn=MySQLdb.connect(
        #host='localhost',
        #port=3306,
        #user='root',
        #passwd='1234',
       # db='zhihu',
      #  charset='uft8'
     #   )
    #cur=conn.cursor()
   # return conn,cur

def get_ip(text):
    '''針對西刺代理網頁編碼建立的規則,此規則只爬取HTTPS類型的代理地址。返回的格式 (ip,端口)'''
    rex=r'''<td class="country"><img src=.*?/></td>\s*?<td>(.*?)</td>\s*?<td>(.*?)</td>\s*?<td>\s*.*\s*</td>\s*?.*\s*?<td>HTTPS</td>'''
    ip=re.findall(rex,text)
    return ip

url=[
    'http://www.xicidaili.com/nn/1',
    'http://www.xicidaili.com/nn/2',
    'http://www.xicidaili.com/nt/1',
    'http://www.xicidaili.com/nt/2',
    'http://www.xicidaili.com/wn/1',
    'http://www.xicidaili.com/wn/2',
    'http://www.xicidaili.com/wt/1',
    'http://www.xicidaili.com/wt/2',
    ]
##爬取西刺代理各分類前兩頁
def create_pool(url):
    '''創建代理池,說白了就是代理列表.起初是打算用隊列的,後來考慮到要驗證每個代理,取出還要再插回去麻煩'''
    headers={
        'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        'Accept-Language':'zh-CN,zh;q=0.8',
        'Cache-Control':'max-age=0',
        'Connection':'keep-alive',
        'Cookie':'_free_proxy_session=BAh7B0kiD3Nlc3Npb25faWQGOgZFVEkiJWIxYjAwZDkxMDE1NWRiYjAwMTBjZTFjZGY3YjJjMjE4BjsAVEkiEF9jc3JmX3Rva2VuBjsARkkiMXE5aGt6cDdPU2tyajI4RjB2dENmZS9aT0RMTDVTK1R2d1hTMDVjUGYxT0E9BjsARg%3D%3D--a913aa7825c13fec2fdfd583519c69b3345ab87b; CNZZDATA1256960793=284076470-1468134027-null%7C1468307148',
        'DNT':'1',
        'Host':'www.xicidaili.com',
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.75 Safari/537.36'
        }
    ##自定義頭,找個瀏覽器開發者模式複製一下
    data=[]
    #用來存儲抓取的原始數據
    proxy_pool=[]
    #初始化代理列表
    #p={'http':'81.139.247.236:80'}
    ##p是一個http代理,有時爬多了西刺代理就禁止訪問了
    ###用代理去爬代理挺那啥的。。所以後面實際使用中可視網站更新狀況自定義輪詢代理網站的時間
    for i in url:
        r=requests.get(i,headers=headers)#如果用代理把代理加進去
        text=r.text
        print r.status_code
        ip=get_ip(text)
        data.extend(ip)
        #用extend是爲了格式上方便,方便遍歷
    for i in data:
        ip=i[0]+':'+i[1]
        #組合ip+port
        proxy_pool.append(ip)
        #存在表裏
    return proxy_pool

def test_proxy(ip,proxy_pool,headers):
    '''測試代理是否可用,免費的代理挺不穩定的。使用率較低'''
    try:
        r=requests.get('https://www.zhihu.com',proxies={'https':ip},headers=headers)
        status=r.status_code
        print 
        if status==200:
            print ip,'200'
        #主要根據返回的狀態碼判斷
            
    except:
        proxy_pool.remove(ip)
        #這一步是拋棄隊列用列表列表的直接原因
        #就感覺很省事。另外也可以避免參數在多個函數間傳遞的問題
        pass
    return proxy_pool
            
headers={
    'Accept':'text/html, application/xhtml+xml, image/jxr, */*',
    'Accept-Language':'zh-CN',
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko',
    'Host':'www.zhihu.com',
    'Connection':'Keep-Alive',
    'Cookie':'n_c=1; __utmc=51854390; q_c1=6879d12c58854a25a7baa63bd647c17f|1468227004000|1468227004000; l_cap_id="NmIzZDAxM2IyNDA4NDUxYmFiYzRhZjBhYjBiZGIxMGM=|1468227004|d39c2d05c63f5a30ac21b24beb6a48e0648c70bb"; cap_id="OWUyMGVhNTAxNjExNDQ5YWE2M2EyODkwYjdkOWNjOGQ=|1468227004|76ebb55701b78072ac6a2ee080d5f0c5dadc292b"; d_c0="AJBAWDZdNgqPTlKnUijCIex0WCt8K2FtfhM=|1468227005"; _zap=884bd241-ddd0-430a-b8ab-97a026efabd0; __utma=51854390.2013250603.1468227006.1468227006.1468227006.1; __utmb=51854390.11.9.1468227042707; __utmz=51854390.1468227006.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmv=51854390.000--|3=entry_date=20160711=1; __utmt=1; _xsrf=179e610b488529dd83ffbfb4bc6a6beb; _za=fa119adb-56a9-4213-a9bc-438a300afd85',
    }
#定義一個訪問知乎的頭

def multi_thread_test(proxy_pool):
    '''上面那個測試可以直接用但時間太長了。所以用併發來解決。不過總體時間還是挺長的'''
    n=len(proxy_pool)
    pool=ThreadPool(n)
    #最大的線程數等於代理總數,這樣就可以所有代理同時跑
    for ip in proxy_pool:
        pool.spawn(test_proxy,ip,proxy_pool,headers)
    gevent.wait()
    return proxy_pool

def test():
    '''測試結果'''
    from time import *
    t1=time()
    proxy_pool=create_pool(url)
    proxy_pool=multi_thread_test(proxy_pool)
    print proxy_pool
    t2=time()
    print t2-t1
test()
    
準備是用來爬知乎的,所以測試網站用的是知乎而不是一些ip查詢站點。對於這測試點我覺得你要用在哪就用哪個網站測試比較好。
代碼在2.7x上課直接運行。對於整體結構性沒怎麼在意。。
其實一直想考慮寫個calss 來結構化一下。。但感覺不到必要性。。。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章