2015-10-06 2 views
0

Мне было интересно, можно ли использовать scrapy Request, чтобы проверить правильность URL-адресов, прежде чем приступать к фактической обработке страницы (URL-адреса неизвестны заранее, но разные шаблоны, в которых они могут быть протестированы). Ниже приведен пример кода, который не работает. (использовал reties переменным для простоты, проверяемое условие может быть также s.th как if response.code != 200 )Пробные/пробные URL-адреса с scapy Request

Код терпит неудачу, потому что по окончанию второго обратного вызова (parse_page_2) контроль не возвращается к первому обратного вызова (parse_page_1), даже если выдается новый запрос, имеющий обратный вызов parse_page_1. Почему это происходит? Я знаю, что решение urllib2 указано here, просто проверяя, может ли это быть выполнено строго в контексте скрининга.

import scrapy 

from scrapy.contrib.spiders import CrawlSpider, Rule 
from scrapy.contrib.linkextractors import LinkExtractor 
from scrapy.http import Request 

class MySpider(CrawlSpider): 
    name = 'alexa' 
    allowed_domains = ['alexa.com'] 
    start_urls = ['http://www.alexa.com'] 
    retries = 0 
    rules = (
     # Extract links matching 'category.php' (but not matching 'subsection.php') 
     # and follow links from them (since no callback means follow=True by default). 
     # Rule(LinkExtractor(allow=('topsites',))), 

     # Extract links matching 'item.php' and parse them with the spider's method parse_item 
     Rule(LinkExtractor(allow=('topsites',)), callback='parse_page1'), 
    ) 

    def parse_page1(self, response): 
     if self.retries < 5: 
      self.retries += 1 
      print 'Retries in 1: ', self.retries 
      return scrapy.Request("http://www.alexa.com/siteieekeknfo/google.com", 
           meta={'dont_merge_cookies': True, 
           'dont_redirect': False, 
           "handle_httpstatus_list": [301, 302, 303, 404]}, 
           callback=self.parse_page2) 
     else: 
      print "Finished in 1" 

    def parse_page2(self, response): 
     if self.retries < 5: 
      self.retries += 1 
      print 'Retries in 2: ', self.retries 
      return scrapy.Request("http://www.alexa.com/siteieekeknfo/google.com", 
           meta={'dont_merge_cookies': True, 
           'dont_redirect': False, 
           "handle_httpstatus_list": [301, 302, 303, 404]}, 
           callback=self.parse_page1) 
     else: 
      print "Finished in 2" 

В результате обхода будет вставлен here.

+0

Вы, вероятно, используют неправильный паук. Попробуйте spiders.Spider и получите прямо из start_requests, так как вы уже знаете свои URL. http://scrapy.readthedocs.org/ru/latest/topics/spiders.html#scrapy-spider – digenishjkl

ответ

0

рекурсивного обратного вызова, кажется, работает:

import random 


from scrapy.contrib.spiders import CrawlSpider, Rule 
from scrapy.contrib.linkextractors import LinkExtractor 
from scrapy.http import Request 

class MySpider(CrawlSpider): 
    name = 'alexa' 
    allowed_domains = ['alexa.com'] 
    start_urls = ['http://www.alexa.com']  
    rules = (
     Rule(LinkExtractor(allow=('topsites',)), callback='parse_page1'), 
    ) 

    _retries = 0 

    _random_urls = [ 
     'http://www.alexa.com/probablydoesnotexist', 
     'http://www.alexa.com/neitherdoesthis', 
     'http://www.alexa.com/siteinfo/google.com' 
    ] 

    def parse_page1(self, response): 
     print "Got status: ", response.status 
     if self._retries == 0 or response.status != 200: 
      self._retries += 1 
      print 'Retries in 1: ', self._retries 
      return Request(random.choice(self._random_urls), 
           meta={"handle_httpstatus_list": [301, 302, 303, 404]}, 
           callback=self.parse_page1) 
     else: 
      print "Exiting"