Cómo usar scrapy.Request para cargar un elemento de otra página en un elemento

He creado un raspador web con Scrapy que puede raspar elementos de cada boleto de este sitio web pero no puede raspar el precio del boleto ya que no está disponible en la página. Cuando trato de solicitar la siguiente página para raspar el precio, no puedo obtener el error: exceptions.TypeError: el objeto ‘XPathItemLoader’ no tiene el atributo ‘ getitem ‘. Solo he podido raspar cualquier elemento usando los cargadores de elementos, así que eso es lo que estoy usando actualmente y no estoy exactamente seguro del procedimiento correcto para pasar elementos raspados en otra página al cargador de elementos (he visto una manera de hacerlo con el tipo de datos del artículo pero no se aplicó aquí). Creo que posiblemente podría haber tenido problemas para extraer elementos en un objeto de elemento porque estoy canalizando en una base de datos, pero no estoy seguro exactamente. Si el código que publico a continuación podría modificarse para rastrear correctamente la página, raspar el precio y agregarlo al cargador de artículos, creo que el problema debería resolverse. Cualquier ayuda será apreciada. ¡Gracias!

class MySpider(CrawlSpider): handle_httpstatus_list = [416] name = 'comparator' allowed_domains = ["www.vividseats.com"] start_urls = [vs_url] tickets_list_xpath = './/*[@itemtype="http://schema.org/Event"]' def parse_price(self, response): #First attempt at trying to load price into item loader loader.add_xpath('ticketPrice' , '//*[@class="eventTickets lastChild"]/div/div/@data-origin-price') print 'ticket price' def parse(self, response): selector = HtmlXPathSelector(response) # iterate over tickets for ticket in selector.select(self.tickets_list_xpath): loader = XPathItemLoader(ComparatorItem(), selector=ticket) # define loader loader.default_input_processor = MapCompose(unicode.strip) loader.default_output_processor = Join() # iterate over fields and add xpaths to the loader loader.add_xpath('eventName' , './/*[@class="productionsEvent"]/text()') loader.add_xpath('eventLocation' , './/*[@class = "productionsVenue"]/span[@itemprop = "name"]/text()') loader.add_xpath('ticketsLink' , './/*/td[3]/a/@href') loader.add_xpath('eventDate' , './/*[@class = "productionsDate"]/text()') loader.add_xpath('eventCity' , './/*[@class = "productionsVenue"]/span[@itemprop = "address"]/span[@itemprop = "addressLocality"]/text()') loader.add_xpath('eventState' , './/*[@class = "productionsVenue"]/span[@itemprop = "address"]/span[@itemprop = "addressRegion"]/text()') loader.add_xpath('eventTime' , './/*[@class = "productionsTime"]/text()') ticketsURL = "concerts/" + bandname + "-tickets/" + bandname + "-" + loader["ticketsLink"] request = scrapy.Request(ticketsURL , callback = self.parse_price) yield loader.load_item() 

Cosas clave para arreglar:

  • para obtener el valor de un cargador de elementos, use get_output_value() , reemplace:

     loader["ticketsLink"] 

    con:

     loader.get_output_value("ticketsLink") 
  • debe pasar el loader dentro del meta de la solicitud y generar / devolver el elemento cargado allí

  • al construir la URL para obtener el precio, use urljoin() para unir la parte relativa con la URL actual

Aquí está la versión fija:

 from urlparse import urljoin # other imports class MySpider(CrawlSpider): handle_httpstatus_list = [416] name = 'comparator' allowed_domains = ["www.vividseats.com"] start_urls = [vs_url] tickets_list_xpath = './/*[@itemtype="http://schema.org/Event"]' def parse_price(self, response): loader = response.meta['loader'] loader.add_xpath('ticketPrice' , '//*[@class="eventTickets lastChild"]/div/div/@data-origin-price') return loader.load_item() def parse(self, response): selector = HtmlXPathSelector(response) # iterate over tickets for ticket in selector.select(self.tickets_list_xpath): loader = XPathItemLoader(ComparatorItem(), selector=ticket) # define loader loader.default_input_processor = MapCompose(unicode.strip) loader.default_output_processor = Join() # iterate over fields and add xpaths to the loader loader.add_xpath('eventName' , './/*[@class="productionsEvent"]/text()') loader.add_xpath('eventLocation' , './/*[@class = "productionsVenue"]/span[@itemprop = "name"]/text()') loader.add_xpath('ticketsLink' , './/*/td[3]/a/@href') loader.add_xpath('eventDate' , './/*[@class = "productionsDate"]/text()') loader.add_xpath('eventCity' , './/*[@class = "productionsVenue"]/span[@itemprop = "address"]/span[@itemprop = "addressLocality"]/text()') loader.add_xpath('eventState' , './/*[@class = "productionsVenue"]/span[@itemprop = "address"]/span[@itemprop = "addressRegion"]/text()') loader.add_xpath('eventTime' , './/*[@class = "productionsTime"]/text()') ticketsURL = "concerts/" + bandname + "-tickets/" + bandname + "-" + loader.get_output_value("ticketsLink") ticketsURL = urljoin(response.url, ticketsURL) yield scrapy.Request(ticketsURL, meta={'loader': loader}, callback = self.parse_price) 

Tengo un problema exacto y lo resolví en otro post. Pongo mi código aquí para compartir: (mi publicación original está aquí )

 from scrapy.spider import Spider from scrapy.selector import Selector from scrapy import Request import re from datetime import datetime, timedelta from CAPjobs.items import CAPjobsItem from CAPjobs.items import CAPjobsItemLoader class CAPjobSpider(Spider): name = "naturejob3" download_delay = 2 #allowed_domains = ["nature.com/naturejobs/"] start_urls = [ "http://www.nature.com/naturejobs/science/jobs?utf8=%E2%9C%93&q=pathologist&where=&commit=Find+Jobs"] def parse_subpage(self, response): il = response.meta['il'] location = response.xpath('//div[@id="extranav"]//ul[@class="job-addresses"]/li/text()').extract() il.add_value('loc_pj', location) yield il.load_item() def parse(self, response): hxs = Selector(response) sites = hxs.xpath('//div[@class="job-details"]') for site in sites: il = CAPjobsItemLoader(CAPjobsItem(), selector = site) il.add_xpath('title', 'h3/a/text()') il.add_xpath('post_date', 'normalize-space(ul/li[@class="when"]/text())') il.add_xpath('web_url', 'concat("http://www.nature.com", h3/a/@href)') url = il.get_output_value('web_url') yield Request(url, meta={'il': il}, callback=self.parse_subpage)