文章目录
IP代理池监控维护器
项目简介(readme)
项目名称
IP代理池监控
项目背景
在爬取一些大网站的时候,总会出现被反爬技术阻碍的情况,限制IP就是其中一种,那么使用代理就是很好的解决方案.
- 爬虫经常会用到代理IP, 高效使用这些IP是一个比较麻烦的事情。
- 代理池是爬虫、采集、爆破、刷单等必不可少的配备。
项目需求
- 需要监控ip是否过期,如果已经过期就从池中删除
- 监控访问目标网址的成功率,将成功率低的自动剔除
- 让ip池长期保持设定的ip数量,以便随时取用
项目技术细节
- 程序需要在服务端24小时运行
- 实时监控,默认2秒频率 apscheduler模块
- redis的有序集合积分板功能作为ip储存,所以程序最好是放于redis同服务器或者同内网上保障实时读写效率
- 提取IP的时候,有效存活时间过短的自动放弃(不入库)自动筛选(自行完成)
- 监控内容:
- 扫描每个IP过期时间,到期删除(自行完成)
- 总个数小于预设值就申请新的IP且值初始ip质量分=1
- ‘ip质量分’ + ‘到期时间戳’ 例如: 101556616966 后面10位是时间戳,前面是分数10(自行完成)。
注意: 分数加减只是对前面2位进行加减,后面10位是时间戳用来比对时间
爬虫模块(spider)
模块内容
批量获取待测ip的"挖掘机"
- ProxyMetaClass作为ProxyMetaClass的元类, 是为了能够动态地生成两个和爬取免费ip的方法有关;
- Crawler类主要定义了一组以crawl_打头的爬取方法,并通过调用主方法get_proxies, 遍历上述爬取方法,
批量爬取一系列proxies,生成的未经有效性检测的ip代理。
代码实现
import re
import sys
from pachong_lagou.config import *
from pachong_lagou.db import RedisClient
from pachong_lagou.test_proxy_vaild import test_proxy_vaild
from pachong_lagou.utils import get_page
from colorama import Fore
from concurrent.futures import ThreadPoolExecutor
import pyquery as pq
class PoolEmptyError(Exception):
def __init__(self):
Exception.__init__(self)
def __str__(self):
return repr('代理池已经枯竭')
# 自定义元类
class ProxyMetaClass(type):
def __new__(cls, name, bases, attrs):
count = 0
attrs['__CrawlFunc__'] = []
for k, v in attrs.items():
if 'crawl_' in k:
attrs['__CrawlFunc__'].append(k)
count += 1
attrs['__CrawlFuncCount__'] = count
return type.__new__(cls, name, bases, attrs)
class Crawler(object, metaclass=ProxyMetaClass):
"""代理池爬虫封装, 支持多个网站的用户代理"""
def get_proxies(self, callback):
for proxy in eval("self.{}()".format(callback)):
yield proxy
def crawl_xicidaili(self):
"""爬取西刺网站的用户代理"""
for page in range(1, 10): # 获取前5页的信息
start_url = 'http://www.xicidaili.com/nn/{}'.format(page) # 构建网址
html = get_page(start_url) # 获取网页内容
if html: # 如果获取成功, 则提取ip和端口
find_trs = re.compile('<tr class.*?>(.*?)</tr>', re.S)
trs = find_trs.findall(html)
for tr in trs:
# 提取ip的正则表达式
find_ip = re.compile('<td>(\d+\.\d+\.\d+\.\d+)</td>')
re_ip_address = find_ip.findall(tr)
# 提取端口的正则表达式
find_port = re.compile('<td>(\d+)</td>')
re_port = find_port.findall(tr)
for address, port in zip(re_ip_address, re_port):
# 用冒号拼接IP和端口# str
address_port = address + ':' + port
# 返回生成器
yield address_port.replace(' ', '')
def crawl_iphai(self):
for page in range(10):
start_url = 'http://www.iphai.com/free/%s' % (page)
html = get_page(start_url)
if html:
find_tr = re.compile('<tr>(.*?)</tr>', re.S)
trs = find_tr.findall(str(html))
for s in range(1, len(trs)):
find_ip = re.compile('<td>\s+(\d+\.\d+\.\d+\.\d+)\s+</td>', re.S)
re_ip_address = find_ip.findall(trs[s])
find_port = re.compile('<td>\s+(\d+)\s+</td>', re