Pergunta

Preciso criar um web spider/crawler configurável pelo usuário e estou pensando em usar o Scrapy.Porém, não consigo codificar os domínios e permitir o URL regex:es - isso será configurável em uma GUI.

Como faço para (o mais simples possível) criar um spider ou um conjunto de spiders com Scrapy onde os domínios e URLs regex:es permitidos são configuráveis ​​dinamicamente?Por exemplo.Eu escrevo a configuração em um arquivo e o spider a lê de alguma forma.

Foi útil?

Solução

AVISO:Esta resposta foi para Scrapy v0.7, a API do gerenciador de aranha mudou muito desde então.

Substitua a classe SpiderManager padrão, carregue suas regras personalizadas de um banco de dados ou de outro lugar e instancie um spider personalizado com suas próprias regras/regexes e nome de domínio

em mybot/settings.py:

SPIDER_MANAGER_CLASS = 'mybot.spidermanager.MySpiderManager'

em mybot/spidermanager.py:

from mybot.spider import MyParametrizedSpider

class MySpiderManager(object):
    loaded = True

    def fromdomain(self, name):
        start_urls, extra_domain_names, regexes = self._get_spider_info(name)
        return MyParametrizedSpider(name, start_urls, extra_domain_names, regexes)

    def close_spider(self, spider):
        # Put here code you want to run before spiders is closed
        pass

    def _get_spider_info(self, name):
        # query your backend (maybe a sqldb) using `name` as primary key, 
        # and return start_urls, extra_domains and regexes
        ...
        return (start_urls, extra_domains, regexes)

e agora sua classe spider personalizada, em mybot/spider.py:

from scrapy.spider import BaseSpider

class MyParametrizedSpider(BaseSpider):

    def __init__(self, name, start_urls, extra_domain_names, regexes):
        self.domain_name = name
        self.start_urls = start_urls
        self.extra_domain_names = extra_domain_names
        self.regexes = regexes

     def parse(self, response):
         ...

Notas:

  • Você também pode estender o CrawlSpider se quiser aproveitar as vantagens de seu sistema de regras
  • Para executar um spider, use: ./scrapy-ctl.py crawl <name>, onde name é passado para SpiderManager.fromdomain e é a chave para recuperar mais informações do spider do sistema backend
  • Como a solução substitui o SpiderManager padrão, codificar um spider clássico (um módulo python por SPIDER) não funciona, mas acho que isso não é um problema para você.Mais informações sobre o gerenciador de spiders padrão TwistedPluginSpiderManager

Outras dicas

O que você precisa é criar classes spider dinamicamente, subclassificando sua classe spider genérica favorita, conforme fornecido por scrapy (CrawlSpider subclasses com seu rules adicionado, ou XmlFeedSpider, ou qualquer outra coisa) e adicionando domain_name, start_urls, e possivelmente extra_domain_names (e/ou start_requests(), etc), conforme você os obtém ou deduz da sua GUI (ou arquivo de configuração, ou qualquer outro).

Python facilita a criação dinâmica de objetos de classe;um exemplo muito simples pode ser:

from scrapy import spider

def makespider(domain_name, start_urls,
               basecls=spider.BaseSpider):
  return type(domain_name + 'Spider',
              (basecls,),
              {'domain_name': domain_name,
               'start_urls': start_urls})

allspiders = []
for domain, urls in listofdomainurlpairs:
  allspiders.append(makespider(domain, urls))

Isso fornece uma lista de classes de aranhas muito básicas - você provavelmente desejará adicionar parse métodos para eles antes de instanciá-los.Tempere a gosto...;-).

Autopromoção descarada em domo!você precisará instanciar o rastreador conforme fornecido nos exemplos, para o seu projeto.

Além disso, você precisará tornar o rastreador configurável em tempo de execução, o que simplesmente passa a configuração para o rastreador e substitui as configurações em tempo de execução, quando a configuração é alterada.

Agora é extremamente fácil configurar o scrapy para estes fins:

  1. Sobre as primeiras URLs a serem visitadas, você pode passá-las como um atributo na chamada do spider com -a, e use o start_requests função para configurar como iniciar o spider

  2. Você não precisa configurar o allowed_domains variável para as aranhas.Se você não incluir essa variável de classe, o spider poderá permitir todos os domínios.

Deve terminar em algo como:

class MySpider(Spider):

    name = "myspider"

    def start_requests(self):
        yield Request(self.start_url, callback=self.parse)


    def parse(self, response):
        ...

e você deve chamá-lo com:

scrapy crawl myspider -a start_url="http://example.com"
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top