#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, не сталкиваясь с проблемой перекрестного пересечения и использования настроек для каждого веб-сайта?
Дополнительное изображение, показывающее, что я хотел бы реализовать:
Ответ №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. Я задавался вопросом, можно ли было бы легко масштабировать это.