搭建代理ip池
阿新 • • 發佈:2018-12-29
在使用爬蟲時,很容易碰到被封ip的情況。遇到這種情況,就需要使用代理ip了。
思路:
1:爬取提供代理ip的網站
2:檢測爬取到的ip是否可用
3:將可用的ip存入資料庫(同時檢測資料庫中是否已存在該ip)
4:呼叫介面,從資料庫中獲取ip(同時檢查資料庫ip的數量,若數量小於5條,就重複以上步驟)
5:若獲取到的ip不可用,則重新獲取,並將不可用的ip從資料庫中刪除
實現:
1:爬取提供代理ip的網站
class ProiexsPool: @staticmethod def _get_proiexs(): # 存放所有ip的列表 ips = []; # 首先爬取代理ip的網站(只爬取前兩頁) for i in range(1,3): html = requests.get("https://www.kuaidaili.com/free/inha/"+str(i)+"/",headers={ "User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0" }).text; # 取出ip和協議型別 html_tree = etree.HTML(html); tr_ips = html_tree.xpath("//tbody/tr"); # print(tr_ips); for index,tr in enumerate(tr_ips): xieyi = tr.xpath("//td[4]/text()")[index]; ip = tr.xpath("//td[1]/text()")[index]+":"+tr.xpath("//td[2]/text()")[index]; # print(type(ip)); # port = ; full_ip = {xieyi : ip}; # 測試ip是否可用 if ProiexsPool._check_ip(full_ip): # 檢視資料庫中是否存在該組ip if ProiexsPool._select_ip_from_database(ip): # 將所有可用的ip存入資料庫 ProiexsPool._save_ip_to_database(xieyi,ip); if i == 2: break; else: time.sleep(5);
2:檢測爬取到的ip是否可用
@staticmethod def _check_ip(ip): """ 檢查ip是否可用的方法 :param ip:要檢查的ip :return: True或者False """ try: # print("正在檢查ip:{}".format(ip)); html = requests.get("http://bj.58.com/chuzu/?PGTID=0d100000-0000-15df-5f6f-34fb3bfd7994&ClickID=3",headers={ "User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0" },proxies=ip,timeout = 3); except Exception as e: print(e); return False; else: if html.status_code == 200: return True; else: return False;
3:檢測資料庫中是否存在該組ip
@staticmethod def _select_ip_from_database(ip): """ 根據傳入的ip查詢,看資料庫中是否有該ip,決定是否儲存該ip :param ip: 要查詢的ip :return: True或False """ try: conn = sqlite3.connect("ProxiesPool.db"); cursor = conn.cursor(); cursor.execute("create table if not exists proxies(xieyi varchar,ip varchar)"); count = cursor.execute("select count(ip) from proxies where ip = '{}'".format(ip)); # print(count); if not count.__next__()[0]: return True; else: return False; except Exception as e: print(e); finally: conn.commit(); cursor.close(); conn.close();
4:若資料庫中不存在某組ip,就將該ip存入資料庫
@staticmethod
def _save_ip_to_database(xieyi,ip):
"""
將ip存入資料庫
:param xieyi: 代理ip的協議(https,http,socket等)
:param ip: 一個ip代理(字典型別)
:return: None
"""
conn = sqlite3.connect("ProxiesPool.db");
cursor = conn.cursor();
cursor.execute("create table if not exists proxies(xieyi varchar,ip varchar)");
cursor.execute("insert into proxies(xieyi ,ip) values ('{}','{}')".format(xieyi,ip));
conn.commit();
cursor.close();
conn.close();
5:從資料庫中隨機獲得一個代理ip供使用者使用
@staticmethod
def _get_random_ip():
"""
隨機獲得一個ip,並檢測資料庫的ip數量
:return: None
"""
conn = sqlite3.connect("ProxiesPool.db");
cursor = conn.cursor();
cursor.execute("create table if not exists proxies(xieyi varchar,ip varchar)");
counts = cursor.execute("select count(*) from proxies")
if counts.__next__()[0] < 5:
# 如果資料庫裡的ip數量小於5個,則往資料庫中重新填入資料
ProiexsPool._get_proiexs();
# 獲得資料庫中所有Ip
proxies = cursor.execute("select * from proxies");
ips = [];
for xieyi,ip in proxies:
ips.append({xieyi : xieyi.lower()+"://"+ip});
conn.commit();
cursor.close();
conn.close();
return random.choice(ips);
6:若從資料庫中隨機獲取到的ip不能使用,則將其從資料庫中刪除
@staticmethod
def _delete_ip_from_db(ip):
"""
根據傳入的ip刪除失效的ip資料
:param ip: 要刪除的ip
:return: None
"""
conn = sqlite3.connect("ProxiesPool.db");
cursor = conn.cursor();
cursor.execute("create table if not exists proxies(xieyi varchar,ip varchar)");
cursor.execute("delete from proxies where ip = '{}'".format(ip));
conn.commit();
cursor.close();
conn.close();
print("成功刪除失效代理ip:{}.....".format(ip));
完整的程式碼可參考我的GitHub:https://github.com/shyorange/CommonlyUsedToolsProjects/blob/master/Proiexs_Pool.py
使用方法:
from Proiexs_Pool import ProiexsPool
pool = ProiexsPool();
pool._get_proiexs();
ip = pool._get_random_ip()
print(ip);