python - source - web crawler linux
Scrapy spider no sigue los enlaces cuando usa Apio (1)
Entonces, después de inspeccionar el código de Scrapy y habilitar el registro de Aplery, insertando estas dos líneas en web_spider.py
:
from celery.utils.log import get_task_logger
logger = get_task_logger(__name__)
Pude localizar el problema: en la función de inicialización de WebSpider
:
super(WebSpider, self).__init__(**kw)
La función __init__
del padre CrawlSpider
llama a la función _compile_rules
que, en suma, copia las reglas de self.rules
a self._rules
mientras realiza algunos cambios. self._rules
es lo que usa la araña cuando busca reglas. Llamar a la función de inicialización de CrawlSpider
antes de definir las reglas llevó a un self._rules
vacío, por lo tanto, no se siguieron enlaces.
Al mover la línea super(WebSpider, self).__init__(**kw)
a la última línea de WebSpider
de __init__
solucionó el problema.
Actualización: hay un pequeño error en el código de la respuesta SO anteriormente mencionada . Hace que el reactor se cuelgue después de la segunda llamada. La solución es simple, en el método __init__
WebCrawlerScript
, simplemente mueva esta línea:
self.crawler.signals.connect(reactor.stop, signal=signals.spider_closed)
fuera de la declaración if, como se sugiere en los comentarios allí.
Actualización 2: ¡Finalmente conseguí tuberías para trabajar! No fue un problema de apio. Me di cuenta de que el módulo de configuración no se estaba leyendo. Fue simplemente un problema de importación. Arreglarlo:
Establezca la variable de entorno SCRAPY_SETTINGS_MODULE
en el módulo de configuración de su proyecto django myproject/settings.py
:
import os
os.environ[''SCRAPY_SETTINGS_MODULE''] = ''myapp.crawler.crawler.settings''
En el módulo de configuración de Scrapy crawler/settings.py
, agregue su ruta de proyecto de sys.path
a sys.path
para que las importaciones relativas en el archivo de configuración funcionen:
import sys
sys.path.append(''/absolute/path/to/scrapy/project'')
Cambie las rutas para adaptarse a su caso.
Estoy escribiendo un rastreador en Python que rastrea todas las páginas en un dominio dado, como parte de un motor de búsqueda específico de un dominio. Estoy usando Django, Scrapy y Apio para lograr esto. El escenario es el siguiente:
Recibo un nombre de dominio del usuario y llamo a la tarea de crawl
dentro de la vista, pasando el dominio como argumento:
crawl.delay(domain)
La tarea en sí misma solo llama a una función que inicia el proceso de rastreo:
from .crawler.crawl import run_spider
from celery import shared_task
@shared_task
def crawl(domain):
return run_spider(domain)
run_spider
inicia el proceso de rastreo, como en esta respuesta SO , reemplazando MySpider
con WebSpider
.
WebSpider
hereda de CrawlSpider
y lo estoy usando ahora solo para probar la funcionalidad. La única regla definida toma una instancia SgmlLinkExtractor
y una función de devolución de llamada parse_page
que simplemente extrae la url de respuesta y el título de la página, rellena un nuevo DjangoItem ( HTMLPageItem
) con ellos y lo guarda en la base de datos (no tan eficiente, lo sé).
from urlparse import urlparse
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from ..items import HTMLPageItem
from scrapy.selector import Selector
from scrapy.contrib.spiders import Rule, CrawlSpider
class WebSpider(CrawlSpider):
name = "web"
def __init__(self, **kw):
super(WebSpider, self).__init__(**kw)
url = kw.get(''domain'') or kw.get(''url'')
if not (url.startswith(''http://'') or url.startswith(''https://'')):
url = "http://%s/" % url
self.url = url
self.allowed_domains = [urlparse(url).hostname.lstrip(''www.'')]
self.start_urls = [url]
self.rules = [
Rule(SgmlLinkExtractor(
allow_domains=self.allowed_domains,
unique=True), callback=''parse_page'', follow=True)
]
def parse_start_url(self, response):
return self.parse_page(response)
def parse_page(self, response):
sel = Selector(response)
item = HTMLPageItem()
item[''url''] = response.request.url
item[''title''] = sel.xpath(''//title/text()'').extract()[0]
item.save()
return item
El problema es que el rastreador solo rastrea los start_urls
y no sigue los enlaces (ni llama a la función de devolución de llamada) cuando sigue este escenario y usa Aplery. Sin embargo, llamar a run_spider
través del python manage.py shell
funciona muy bien.
Otro problema es que Item Pipelines y logging no funcionan con Apio. Esto está haciendo que la depuración sea mucho más difícil. Creo que estos problemas podrían estar relacionados.