Start crawling

        This method will start feeder, parser and download and wait
        until all threads exit.

        Args:
            feeder_kwargs (dict, optional): Arguments to be passed to ``feeder.start()``
            parser_kwargs (dict, optional): Arguments to be passed to ``parser.start()``
            downloader_kwargs (dict, optional): Arguments to be passed to
                ``downloader.start()``

def crawl(self,
              feeder_kwargs=None,
              parser_kwargs=None,
              downloader_kwargs=None):
        """Start crawling

        This method will start feeder, parser and download and wait
        until all threads exit.

        Args:
            feeder_kwargs (dict, optional): Arguments to be passed to ``feeder.start()``
            parser_kwargs (dict, optional): Arguments to be passed to ``parser.start()``
            downloader_kwargs (dict, optional): Arguments to be passed to
                ``downloader.start()``
        """
        self.signal.reset()
        self.logger.info('start crawling...')

        feeder_kwargs = {} if feeder_kwargs is None else feeder_kwargs
        parser_kwargs = {} if parser_kwargs is None else parser_kwargs
        downloader_kwargs = {} if downloader_kwargs is None else downloader_kwargs

        self.logger.info('starting %d feeder threads...',
                         self.feeder.thread_num)
        self.feeder.start(**feeder_kwargs)

        self.logger.info('starting %d parser threads...',
                         self.parser.thread_num)
        self.parser.start(**parser_kwargs)

        self.logger.info('starting %d downloader threads...',
                         self.downloader.thread_num)
        self.downloader.start(**downloader_kwargs)

        while True:
            if not self.feeder.is_alive():
                self.signal.set(feeder_exited=True)
            if not self.parser.is_alive():
                self.signal.set(parser_exited=True)
            if not self.downloader.is_alive():
                break
            time.sleep(1)

        if not self.feeder.in_queue.empty():
            self.feeder.clear_buffer()
        if not self.parser.in_queue.empty():
            self.parser.clear_buffer()
        if not self.downloader.in_queue.empty():
            self.downloader.clear_buffer(True)

        self.logger.info('Crawling task done!')