代理池是爬虫、采集、爆破、刷单等必不可少的配备。读了一个github的py代理池的源码,简单易用免维护,也无需过多配置,该程序从网站爬取代理列表,存入SQLite数据库。定时执行爬取->存入->检查->爬取的循环以保证采集到代理IP的可用性。
开两个线程,一个用做服务器对外提供代理IP,另一个用于维护代理池里IP的可用性。
线程1
def _api(self): ProxyServer(API_CONFIG[\'PORT\']) class ProxyServer: def __init__(self, port): self.port = int(port) self.run() .... def run(self): http_server = HTTPServer((\'localhost\', self.port), self.ProxyPoolHandler) logger.info(\'listened on localhost:%s\' % API_CONFIG[\'PORT\']) http_server.serve_forever()
二、本地搭建HTTP服务,使用URL参数作为筛选条件从数据库中筛出符合条件的代理并以json格式返回。
def get_proxy(self, params): where_dict = {\'port\': \'port\', \'type\': \'type\', \'protocol\': \'protocol\', \'area\': \'area\'} conds = { \'field\': [\'ip\', \'port\'], \'order\': [\'updatetime desc\', \'lastusedtime\', \'score desc\', \'speed\'], \'limit\': 1, \'where\': [], } if params: for (k, v) in params.items(): try: if k == \'num\': conds[\'limit\'] = v[0] elif k == \'area\': conds[\'where\'].append((where_dict[k], \'like\', \'%%%s%%\' % v[0])) else: conds[\'where\'].append((where_dict[k], \'=\', v[0])) except: continue data = self.sqlite.select(self.table_name, conds) tmp = [{\'ip\': n[0], \'port\': n[1], \'lastusedtime\': datetime.datetime.now().strftime(\'%Y-%m-%d %H:%M:%S\')} for n in data] self.sqlite.update(self.table_name, tmp) data = [\'%s:%s\' % n for n in data] return json.dumps(data)
因为每个加入代理池的ip都设置了过期时间,所以检查代理ip是否有效这个操作,也并非真的去检验ip本身,而是检查它的过期时间。
线程2
def _monitor(self): while True: self._update(PROXYPOOL_CONFIG[\'UPDATE_TIME\']) self._delete(PROXYPOOL_CONFIG[\'DELETE_TIME\']) self._crawl(PROXYPOOL_CONFIG[\'CRAWL_TIME\']) time.sleep(1800) 我们需要清除掉过期时间<当前时间的ip。 # -*- coding: utf-8 -*- # @File : delele_ip.py # @Author: AaronJny # @Date : 18-12-14 上午11:15 # @Desc : 过期ip清理器 import utils import settings import time class ExpireIpCleaner: def __init__(self): self.logger = utils.get_logger(getattr(self.__class__, \'__name__\')) self.server = utils.get_redis_client() def clean(self): """ 清理代理池中的过期ip :return: """ self.logger.info(\'开始清理过期ip\') # 计算清理前代理池的大小 total_before = int(self.server.zcard(settings.IP_POOL_KEY)) # 清理 self.server.zremrangebyscore(settings.IP_POOL_KEY, 0, int(time.time())) # 计算清理后代理池的大小 total_after = int(self.server.zcard(settings.IP_POOL_KEY)) self.logger.info(\'完毕!清理前可用ip {},清理后可用ip {}\'.format(total_before, total_after)) def main(self): """ 周期性的清理过期ip :return: """ while True: self.clean() self.logger.info(\'*\' * 40) time.sleep(settings.CLEAN_INTERVAL) if __name__ == \'__main__\': ExpireIpCleaner().main()