2011-04-28 19 views
21

Tengo una pregunta sobre cómo hacer esto en la terapia. Tengo una araña que se arrastra para enumerar páginas de elementos. Cada vez que se encuentra una página de listado, con elementos, está la devolución de llamada parse_item() que se llama para extraer datos de elementos y generar elementos. Hasta ahora todo bien, todo funciona bien.Scrapy - analizar una página para extraer elementos - luego seguir y almacenar contenido de la URL del elemento

Pero cada elemento tiene, entre otros datos, una url, con más detalles sobre ese elemento. Quiero seguir esa URL y almacenar en otro campo de elemento (url_contents) el contenido recuperado de la URL de ese elemento.

Y no estoy seguro de cómo organizar el código para lograr eso, ya que los dos enlaces (enlace de listados y un enlace de elemento particular) se siguen de manera diferente, con devoluciones de llamada en diferentes momentos, pero tengo que correlacionarlos en el mismo procesamiento de elementos.

Mi código hasta ahora se ve así:

class MySpider(CrawlSpider): 
    name = "example.com" 
    allowed_domains = ["example.com"] 
    start_urls = [ 
     "http://www.example.com/?q=example", 
    ] 

    rules = (
     Rule(SgmlLinkExtractor(allow=('example\.com', 'start='), deny=('sort='), restrict_xpaths = '//div[@class="pagination"]'), callback='parse_item'), 
     Rule(SgmlLinkExtractor(allow=('item\/detail',)), follow = False), 
    ) 


    def parse_item(self, response): 
     main_selector = HtmlXPathSelector(response) 
     xpath = '//h2[@class="title"]' 

     sub_selectors = main_selector.select(xpath) 

     for sel in sub_selectors: 
      item = ExampleItem() 
      l = ExampleLoader(item = item, selector = sel) 
      l.add_xpath('title', 'a[@title]/@title') 
      ...... 
      yield l.load_item() 

Respuesta

19

Después de algunas pruebas y pensamientos, encontré esta solución que funciona para mí. La idea es usar solo la primera regla, que le da listados de artículos, y también, muy importante, agregar follow = True a esa regla.

Y en parse_item() debe realizar una solicitud en lugar de un elemento, pero después de cargar el elemento. La solicitud es para el detalle del elemento url. Y debe enviar el artículo cargado a esa devolución de llamada de solicitud. Usted hace su trabajo con la respuesta, y allí es donde cede el artículo.

Así el acabado de parse_item() se verá así:

itemloaded = l.load_item() 

# fill url contents 
url = sel.select(item_url_xpath).extract()[0] 
request = Request(url, callback = lambda r: self.parse_url_contents(r)) 
request.meta['item'] = itemloaded 

yield request 

Y luego parse_url_contents() tendrá el siguiente aspecto:

def parse_url_contents(self, response): 
    item = response.request.meta['item'] 
    item['url_contents'] = response.body 
    yield item 

Si alguien tiene otro enfoque (mejor), y mucho sabemos.

Stefan

+0

Eso es como lo hago. Creo que la única alternativa es reagrupar los datos en la etapa de almacenamiento/producción. – Acorn

+0

Sí, también tenemos confirmación en el grupo de terapia, así que he elegido mi respuesta – StefanH

1

estoy sentado con exactamente el mismo problema, y ​​del hecho de que nadie ha respondido a su pregunta durante 2 días ¿Puedo entender que la única La solución es seguir esa URL manualmente, desde su función parse_item.

Soy nuevo en Scrapy, así que no lo intentaría con eso (aunque estoy seguro de que es posible), pero mi solución será utilizar urllib y BeatifulSoup para cargar la segunda página manualmente, extraer esa información yo mismo, y guardarlo como parte del artículo. Sí, mucho más problemas que Scrapy hace el análisis normal, pero debería hacer el trabajo con la menor molestia.

Cuestiones relacionadas