He conseguido codificar una oruga muy simple con Scrapy, con estas restricciones dadas:¿Por qué no funcionan mis reglas de Scrapy CrawlSpider?
- tienda toda la información de enlace (por ejemplo: el ancla de texto, título de la página), por lo tanto, las devoluciones de llamada 2
- Uso CrawlSpider a Aproveche las reglas, por lo tanto, no BaseSpider
Funciona bien, excepto que no implementa reglas si agrego una devolución de llamada a la primera solicitud.
Aquí está mi código: (obras, pero no correctamente, con un ejemplo vivo)
from scrapy.contrib.spiders import CrawlSpider,Rule
from scrapy.selector import HtmlXPathSelector
from scrapy.http import Request
from scrapySpider.items import SPage
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
class TestSpider4(CrawlSpider):
name = "spiderSO"
allowed_domains = ["cumulodata.com"]
start_urls = ["http://www.cumulodata.com"]
extractor = SgmlLinkExtractor()
def parse_start_url(self, response):
#3
print('----------manual call of',response)
self.parse_links(response)
print('----------manual call done')
# 1 return Request(self.start_urls[0]) # does not call parse_links(example.com)
# 2 return Request(self.start_urls[0],callback = self.parse_links) # does not call parse_links(example.com)
rules = (
Rule(extractor,callback='parse_links',follow=True),
)
def parse_links(self, response):
hxs = HtmlXPathSelector(response)
print('----------- manual parsing links of',response.url)
links = hxs.select('//a')
for link in links:
title = link.select('@title')
url = link.select('@href').extract()[0]
meta={'title':title,}
yield Request(url, callback = self.parse_page,meta=meta)
def parse_page(self, response):
print('----------- parsing page: ',response.url)
hxs = HtmlXPathSelector(response)
item=SPage()
item['url'] = str(response.request.url)
item['title']=response.meta['title']
item['h1']=hxs.select('//h1/text()').extract()
yield item
He intentado resolver este problema en 3 maneras:
- 1: Para devolver una Solicitud con la url de inicio - reglas no se ejecutan
- 2: Igual que el anterior, pero con una devolución de llamada a
parse_links
- mismo problema - 3: Llamada
parse_links
después raspando la URL de inicio, mediante la implementación deparse_start_url
, la función no se consiga llamar
Estos son los registros:
----------manual call of <200 http://www.cumulodata.com>)
----------manual call done
#No '----------- manual parsing links', so `parse_links` is never called!
Versiones
- Python 2.7.2
- Scrapy 0.14.4
Muchas gracias a Anuj por sus esfuerzos para resolver este problema. ¡Definitivamente no lo habría resuelto solo! Agregaré luego unos pocos pasos para deshacerme del parámetro? 1 justo antes de guardar el ítem, (probablemente en una tubería), y será perfecto. Implementé de hecho el sitio de prueba para duplicar lo que puede suceder en la vida real;) – arno
Para entender completamente cuál era el problema, la principal dificultad planteada por mi crawlr es que estoy lanzando solicitudes en url que ya están en la cola procesada por el planificador , puesto allí por el propio CrawlSpider a través de las Reglas, ¿verdad? ¿Así que te deshiciste de esto al usar diferentes URL para el CrawlSpider (sin? 1) y para mi propio push de Solicitud (con el parámetro adicional? 1), ¿estoy en lo cierto? – arno
Tiene razón, Scrapy no rastrea las URL duplicadas (por una buena razón). Como lo necesitábamos, modificamos la URL. Podría haber usado 'dont_filter = True' pero el sitio web de prueba está muy interconectado y produjo demasiados duplicados, por lo que creamos un conjunto adicional de URL. Ya conoce los otros dos problemas: 1. Las reglas no se ejecutan para una solicitud de inicio con devolución de llamada personalizada, 2. 'parse_links' no se estaba llamando correctamente. –