Сканирование нескольких доменов с помощью Scrapy без перекрестного

#python #scrapy

#python #scrapy

Вопрос:

Я настроил CrawlSpider, объединяющий все исходящие ссылки (сканирование start_urls только с определенной глубины, например, через DEPTH_LIMIT = 2 ).

 class LinkNetworkSpider(CrawlSpider):

    name = "network"
    allowed_domains = ["exampleA.com"]

    start_urls = ["http://www.exampleA.com"]

    rules = (Rule(SgmlLinkExtractor(allow=()), callback='parse_item', follow=True),)

    def parse_start_url(self, response):
        return self.parse_item(response)

    def parse_item(self, response):

        hxs = HtmlXPathSelector(response)
        links = hxs.select('//a/@href').extract()

        outgoing_links = []

        for link in links:
            if ("http://" in link):
                base_url = urlparse(link).hostname
                base_url = base_url.split(':')[0]  # drop ports
                base_url = '.'.join(base_url.split('.')[-2:])  # remove subdomains
                url_hit = sum(1 for i in self.allowed_domains if base_url not in i)
                if url_hit != 0:
                    outgoing_links.append(link)

        if outgoing_links:
            item = LinkNetworkItem()
            item['internal_site'] = response.url
            item['out_links'] = outgoing_links
            return [item]
        else:
            return None
  

Я хочу распространить это на несколько доменов (exampleA.com , exampleB.com , exampleC.com …). Сначала я подумал, что могу просто добавить свой список в start_urls а также, allowed_domains но, на мой взгляд, это вызывает следующие проблемы:

  • DEPTH_LIMIT Будут ли применены настройки для каждого start_urls / allowed_domain ?
  • Что еще более важно: если сайты подключены, будет ли паук прыгать с exampleA.com чтобы exampleB.com потому что оба находятся в allowed_domains? Мне нужно избегать этого перекрестного обхода, поскольку позже я захочу подсчитать исходящие ссылки для каждого сайта, чтобы получить информацию о взаимосвязи между сайтами!

Итак, как я могу увеличить масштаб spider, не сталкиваясь с проблемой перекрестного пересечения и использования настроек для каждого веб-сайта?

Дополнительное изображение, показывающее, что я хотел бы реализовать: scrapy

Ответ №1:

Теперь я достиг этого без правил. Я прикрепил meta атрибут к каждому start_url , а затем просто проверил, принадлежат ли ссылки исходному домену, и соответственно отправил новые запросы.

Поэтому переопределите start_requests :

 def start_requests(self):
    return [Request(url, meta={'domain': domain}, callback=self.parse_item) for url, domain in zip(self.start_urls, self.start_domains)]
  

В последующих методах синтаксического анализа мы захватываем meta атрибут domain = response.request.meta['domain'] , сравниваем домен с извлеченными ссылками и сами отправляем новые запросы.

Ответ №2:

Вероятно, вам потребуется сохранить структуру данных (например, хэш-карту) URL-адресов, которые уже посетил искатель. Тогда это просто вопрос добавления URL-адресов в hashmap по мере их посещения, а не посещения URL-адресов, если они уже есть в hashmap (поскольку это означает, что вы их уже посетили). Вероятно, есть более сложные способы сделать это, которые дали бы вам большую производительность, но их также было бы сложнее реализовать.

Комментарии:

1. Ну, scrapy это уже реализовано, если вы передаете один start_url и один allowed_domain. Я задавался вопросом, можно ли было бы легко масштабировать это.