前言
作為一個爬蟲框架,與其他爬蟲差異為:靈活擴展以及入門簡單
整體架構(gòu)
- 調(diào)度器
從請求管理器中取請求,然后調(diào)用下載器進行下載,調(diào)度解析器進行解析蝶锋,對解析出的請求再次加入到請求管理器中;解析出的數(shù)據(jù)進行緩存什往,最后寫入到文本中
調(diào)度器為爬蟲框架的核心扳缕,也是爬蟲的入口,其成員變量為下載器、解析器躯舔、請求管理器驴剔、文件寫入類、日志類粥庄,對于不同的爬蟲需求丧失,可以對以上接口有不同的實現(xiàn)。
核心方法:
從請求管理器中取用 request,采用模板設(shè)計模式惜互,不可被子類重寫
def run(self, request):
'''
運行爬蟲方法布讹,從requestManager中取出可用的request,然后扔進下載器中進行下載训堆,通過解析器對下載到的文檔進行解析描验;
需要傳入一個或者一組request作為初始request進行抓取
@param :: request : Request類型請求
return : None
'''
self.__start_icon()
self.__logger.info('\tStart crawl...')
self.__requestManager.add_new_request(request)
while self.__requestManager.has_new_request():
request = self.__requestManager.get_new_request()
print(request.__dict__)
self.crawl(request)
self.__logger.info('\tEnd crawl...')
- 調(diào)度下載器與解析器,可被子類繼承擴展坑鱼,可擴展為多線程膘流、多進程等
def crawl(self, request):
'''
對request進行請求進行爬取并解析結(jié)果的運行單元,子類可對該方法重寫進行多線程鲁沥、多進程運行或異步抓取與解析呼股;也可裝飾該方法,進行多線程画恰、多進程抓取彭谁。
下載器對傳入的request進行下載,解析器解析下載到的文檔阐枣,并將解析出的request扔進requestManager中進行管理马靠,以進行深度爬取蔼两;將解析出的data扔進writter中,將數(shù)據(jù)存儲到磁盤上
@param :: request : Request類型請求
return None
'''
try:
self.__logger.info('\t'+request.url)
response = self.__downloader.download(request)
if response.status_code == 200:
requests, data = self.__parser.parse(response)
self.__requestManager.add_new_requests(requests)
self.__writter.write_buffer(data)
else:
self.__logger.warn(
'crawled data is None and response_status is ' + str(response.status_code))
except Exception as e:
self.__logger.exception('\tCrawling occurs error\n' + e.__repr__())
- 下載器
對傳入的請求進行請求下載
抽象方法:
def download(self, request):
'''
對request進行請求下載逞度,需要將請求到的response返回
@param :: request : 請求對象
return response
'''
raise NotImplementedError("未實現(xiàn)的父類方法: %s.%s" % (
self.__class__.__name__, get__function_name()))
- 解析器
對傳入的文本進行解析
抽象方法:
def parse(self, response):
'''
對response進行解析额划,需要將解析到的requests與data返回
@param :: response : 響應(yīng)對象
return requests,data
'''
raise NotImplementedError("未實現(xiàn)的父類方法: %s.%s" % (
self.__class__.__name__, get__function_name()))
- 請求管理器
管理所有的請求
抽象方法:
def add_new_requests(self, requests):
'''
模板方法,不需要子類重寫
添加requests序列到requestManager中進行管理
@param :: requests : request對象列表
return None
'''
for request in requests:
self.add_new_request(request)
def add_new_request(self, request):
'''
添加request對象到requestManager中進行管理
@param :: request : request對象
return None
'''
raise NotImplementedError("未實現(xiàn)的父類方法: %s.%s" % (
self.__class__.__name__, get__function_name()))
def has_new_request(self):
'''
判斷requestManager中是否還有新的請求档泽,返回布爾類型結(jié)果
return Bool
'''
raise NotImplementedError("未實現(xiàn)的父類方法: %s.%s" % (
self.__class__.__name__, get__function_name()))
def get_new_request(self):
'''
從requestManager中取新的請求
return request
'''
raise NotImplementedError("未實現(xiàn)的父類方法: %s.%s" % (
self.__class__.__name__, get__function_name()))
- 數(shù)據(jù)寫入類
將數(shù)據(jù)以特定格式寫入到磁盤中
抽象方法:
def write(self, data):
'''
將數(shù)據(jù)data寫入磁盤
return None
'''
raise NotImplementedError("未實現(xiàn)的父類方法: %s.%s" % (
self.__class__.__name__, get__function_name()))
def write_buffer(self, data):
'''
緩存數(shù)據(jù)
return None
'''
raise NotImplementedError("未實現(xiàn)的父類方法: %s.%s" % (
self.__class__.__name__, get__function_name()))
def flush_buffer(self):
'''
刷新緩存數(shù)據(jù)到磁盤上
return None
'''
raise NotImplementedError("未實現(xiàn)的父類方法: %s.%s" % (
self.__class__.__name__, get__function_name()))
- 日志
記錄爬蟲運行
抽象方法:
def debug(self, message):
'''
debug級別日志
'''
raise NotImplementedError("未實現(xiàn)的父類方法: %s.%s" % (
self.__class__.__name__, get__function_name()))
def info(self, message):
'''
info級別日志
'''
raise NotImplementedError("未實現(xiàn)的父類方法: %s.%s" % (
self.__class__.__name__, get__function_name()))
def warn(self, message):
'''
warn級別日志
'''
raise NotImplementedError("未實現(xiàn)的父類方法: %s.%s" % (
self.__class__.__name__, get__function_name()))
def exception(self, message):
'''
exception級別日志
'''
raise NotImplementedError("未實現(xiàn)的父類方法: %s.%s" % (
self.__class__.__name__, get__function_name()))
def error(self, message):
'''
error級別日志
'''
raise NotImplementedError("未實現(xiàn)的父類方法: %s.%s" % (
self.__class__.__name__, get__function_name()))
設(shè)計思想
在 Abstract Factory 模式為將’抽象零件’組裝為’抽象產(chǎn)品’俊戳,因此對于下載器、解析器馆匿、請求管理器抑胎、數(shù)據(jù)寫入類、日志類僅是限定其抽象接口渐北,在調(diào)度器中分別調(diào)用其每個零件的具體實現(xiàn)阿逃。
調(diào)度器則參照了模板方法設(shè)計模式,將開始爬取方法(startcrawl)固定,對于調(diào)度器的多線程多進程擴展可繼承該調(diào)度器恃锉,并重寫調(diào)度爬取方法(crawl)搀菩,提供多線程多進程爬取方法
在爬蟲整體框架設(shè)計中,主體未調(diào)度器破托、下載器肪跋、解析器、請求管理器土砂、數(shù)據(jù)寫入類州既、日志類,滿足了基本爬蟲的需求萝映,在實際中爬蟲進行爬取數(shù)據(jù)時吴叶,需要設(shè)置網(wǎng)絡(luò)代理、設(shè)置不同的 cookie 身份锌俱、以及分布式爬取調(diào)度任務(wù)等晤郑,可對以上基本組件運用裝飾者模式進行裝飾,已達到擴展功能的需求
小白文章贸宏,還請各位多多請教造寝!