2015-10-23 3 views
1

Таким образом, мой паук занимает список веб-сайтов, и он проскакивает через каждый через start_requests, который yieldrequest, проходящий в item как meta.Когда нужно вернуть Предмет, если я не знаю, когда паук закончит?

Затем паук исследует все внутренние ссылки одного веб-сайта и собирает все внешние ссылки в item. Проблема в том, что я не знаю, когда паук заканчивает сканирование всех внутренних ссылок, поэтому я не могу yielditem.

class WebsiteSpider(scrapy.Spider): 
    name = "web" 

    def start_requests(self): 
     filename = "websites.csv" 
     requests = [] 
     try: 
      with open(filename, 'r') as csv_file: 
       reader = csv.reader(csv_file) 
       header = next(reader) 
       for row in reader: 
        seed_url = row[1].strip() 
        item = Links(base_url=seed_url, on_list=[]) 
        request = Request(seed_url, callback=self.parse_seed) 
        request.meta['item'] = item 
        requests.append(request) 
      return requests 
     except IOError: 
      raise scrapy.exceptions.CloseSpider("A list of websites are needed") 

    def parse_seed(self, response): 
     item = response.meta['item'] 
     netloc = urlparse(item['base_url']).netloc 
     external_le = LinkExtractor(deny_domains=netloc) 
     external_links = external_le.extract_links(response) 
     for external_link in external_links: 
      item['on_list'].append(external_link) 

     internal_le = LinkExtractor(allow_domains=netloc) 
     internal_links = internal_le.extract_links(response) 

     for internal_link in internal_links: 
      request = Request(internal_link, callback=self.parse_seed) 
      request.meta['item'] = item 
      yield request 
+0

Можете ли вы показать свой текущий код паука? Благодарю. – alecxe

+0

@alecxe Отредактировано! –

ответ

0

start_requests метод должен давать Request объекты. Вам не нужно возвращать список запросов, но только давать запрос, когда он будет готов, это работает, потому что запросы scrapy являются асинхронными.

То же самое происходит с товарами, вам просто нужно давать свои товары, когда вы думаете, что товар готов, я бы порекомендовал для вашего случая просто проверить, нет ли более internal_links, чтобы получить товар, а также вы можете многие пункты, как вы хотите, а затем проверить, какой из них был последним (или один с большим количеством данных):

class WebsiteSpider(scrapy.Spider): 
    name = "web" 

    def start_requests(self): 
     filename = "websites.csv" 
     requests = [] 
     try: 
      with open(filename, 'r') as csv_file: 
       reader = csv.reader(csv_file) 
       header = next(reader) 
       for row in reader: 
        seed_url = row[1].strip() 
        item = Links(base_url=seed_url, on_list=[]) 
        yield Request(seed_url, callback=self.parse_seed, meta = {'item'=item}) 
     except IOError: 
      raise scrapy.exceptions.CloseSpider("A list of websites are needed") 

    def parse_seed(self, response): 
     item = response.meta['item'] 
     netloc = urlparse(item['base_url']).netloc 
     external_le = LinkExtractor(deny_domains=netloc) 
     external_links = external_le.extract_links(response) 
     for external_link in external_links: 
      item['on_list'].append(external_link) 

     internal_le = LinkExtractor(allow_domains=netloc) 
     internal_links = internal_le.extract_links(response) 
     if internal_links: 
      for internal_link in internal_links: 
       request = Request(internal_link, callback=self.parse_seed) 
       request.meta['item'] = item 
       yield request 
     else: 
      yield item 

другая вещь, которую вы могли бы сделать, это создать extension, чтобы делать то, что вам нужно по методу spider_closed и делать что бы вы ни знали, когда паук закончил.

+0

Спасибо за ответ. Я думал о том, чтобы уступить, когда закончились внутренние ссылки, но, как вы упомянули, поскольку scrapy выполняется асинхронно, даже если эта определенная веб-страница не имеет каких-либо внутренних ссылок, некоторые другие веб-страницы могут находиться в очереди, ожидающей обработки. Я перестроил scrapy с загрузчиком элементов, и я думаю, что могу просто создать новую функцию, которая принимает словарь и выводит его в JSON после вызова 'closed'. –

+0

отлично, так что вы собираетесь создать собственное расширение? Я думаю, что это лучший результат, и в то же время уступая предметы, может помочь вам записать, как работает паук, раньше я делал что-то подобное. – eLRuLL

+0

Возможно, вам придется обучить меня по этой проблеме, но я не понимаю преимуществ использования расширения. Из того, что я читал, это просто похоже на реализацию класса Python или функции? То, что я пытаюсь сделать, это вернуть JSON, когда паук завершает сканирование через все семенные веб-сайты, и я думаю ['closed'] (http://doc.scrapy.org/en/latest/topics/spiders.html? highlight = closed # scrapy.spiders.Spider.closed) обрабатывает это, поэтому мне нужно будет просто реализовать экспортер JSON, который будет вызываться после вызова 'closed'. –