程序員解決爬蟲IP被封的神器

代理池是爬蟲、採集、爆破、刷單等必不可少的配備。讀了一個github的py代理池的源碼,簡單易用免維護,也無需過多配置,該程序從網站爬取代理列表,存入SQLite數據庫。定時執行爬取->存入->檢查->爬取的循環以保證採集到代理IP的可用性。
開兩個線程,一個用作服務器對外提供代理IP,另外一個用於維護代理池裏IP的可用性。
線程1git

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()

2、本地搭建HTTP服務,使用URL參數做爲篩選條件從數據庫中篩出符合條件的代理並以json格式返回。github

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自己,而是檢查它的過時時間。
線程2redis

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 utilsimport settingsimport timeclass 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()

 
相關文章
相關標籤/搜索