urljoin tutorial spider mercadolibre example español create python web-scraping scrapy scrapy-spider

python - tutorial - scrapy spider



¿Cómo puedo reutilizar el método de análisis de mi araña basada araña scrapy en un CrawlSpider heredado? (1)

Actualmente tengo una araña basada en Spider que escribí para rastrear una matriz JSON de entrada de start_urls :

from scrapy.spider import Spider from scrapy.contrib.spiders import CrawlSpider, Rule from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor from foo.items import AtlanticFirearmsItem from scrapy.contrib.loader import ItemLoader import json import datetime import re class AtlanticFirearmsSpider(Spider): name = "atlantic_firearms" allowed_domains = ["atlanticfirearms.com"] def __init__(self, start_urls=''[]'', *args, **kwargs): super(AtlanticFirearmsSpider, self).__init__(*args, **kwargs) self.start_urls = json.loads(start_urls) def parse(self, response): l = ItemLoader(item=AtlanticFirearmsItem(), response=response) product = l.load_item() return product

Puedo llamarlo desde la línea de comandos como tal, y hace un trabajo maravilloso:

scrapy crawl atlantic_firearms -a start_urls=''["http://www.atlanticfirearms.com/component/virtuemart/shipping-rifles/ak-47-receiver-aam-47-detail.html", "http://www.atlanticfirearms.com/component/virtuemart/shipping-accessories/nitride-ak47-7-62x39mm-barrel-detail.html"]''

Sin embargo, estoy tratando de agregar una araña basada en CrawlSpider para rastrear todo el sitio que hereda de ella y volver a utilizar la lógica del método de parse . Mi primer intento se veía así:

class AtlanticFirearmsCrawlSpider(CrawlSpider, AtlanticFirearmsSpider): name = "atlantic_firearms_crawler" start_urls = [ "http://www.atlanticfirearms.com" ] rules = ( # I know, I need to update these to LxmlLinkExtractor Rule(SgmlLinkExtractor(allow=[''detail.html'']), callback=''parse''), Rule(SgmlLinkExtractor(allow=[], deny=[''/bro'', ''/news'', ''/howtobuy'', ''/component/search'', ''askquestion''])), )

Ejecutando esta araña con

scrapy crawl atlantic_firearms_crawler

rastrea el sitio pero nunca analiza ningún elemento. Creo que es porque CrawlSpider aparentemente tiene su propia definición de parse , así que de alguna manera estoy arruinando las cosas.

Cuando cambio la callback=''parse'' a callback=''parse_item'' y cambio el nombre del método de parse en AtlanticFirearmsSpider a parse_item , funciona de maravilla, parse_item todo el sitio y analiza los elementos con éxito. Pero si trato de llamar a mi araña atlantic_firearms original de nuevo, se NotImplementedError un error con NotImplementedError , aparentemente porque las arañas basadas en arañas realmente quieren que se defina el método parse como parse .

¿Cuál es la mejor manera de reutilizar mi lógica entre estas arañas para que pueda tanto alimentar una matriz JSON de start_urls como hacer start_urls de sitio completo?


Puede evitar herencia múltiple aquí .

Combina ambas arañas en una sola. Si start_urls se pasa desde la línea de comandos, se comportaría como un CrawlSpider , de lo contrario, como un spider regular:

from scrapy import Item from scrapy.contrib.spiders import CrawlSpider, Rule from foo.items import AtlanticFirearmsItem from scrapy.contrib.loader import ItemLoader from scrapy.contrib.linkextractors import LinkExtractor import json class AtlanticFirearmsSpider(CrawlSpider): name = "atlantic_firearms" allowed_domains = ["atlanticfirearms.com"] def __init__(self, start_urls=None, *args, **kwargs): if start_urls: self.start_urls = json.loads(start_urls) self.rules = [] self.parse = self.parse_response else: self.start_urls = ["http://www.atlanticfirearms.com/"] self.rules = [ Rule(LinkExtractor(allow=[''detail.html'']), callback=''parse_response''), Rule(LinkExtractor(allow=[], deny=[''/bro'', ''/news'', ''/howtobuy'', ''/component/search'', ''askquestion''])) ] super(AtlanticFirearmsSpider, self).__init__(*args, **kwargs) def parse_response(self, response): l = ItemLoader(item=AtlanticFirearmsItem(), response=response) product = l.load_item() return product

O, como alternativa, simplemente extraiga la lógica dentro del método parse() en una función de biblioteca y llame desde ambas arañas que no estarían relacionadas, arañas separadas.