使用Scrapy爬取多个域名不交叉
我设置了一个爬虫,专门收集所有的外部链接(只从 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
都生效吗? - 更重要的是:如果这些网站之间有连接,爬虫会不会因为两个域名都在
allowed_domains
中而从 exampleA.com 跳到 exampleB.com?我需要避免这种交叉,因为我之后想统计每个网站的外部链接,以了解网站之间的关系!
那么,我该如何扩展更多的爬虫,而不遇到 交叉 的问题,并且能为每个网站使用不同的设置呢?
附加的图片展示了我想实现的效果:
2 个回答
1
你可能需要保持一个数据结构(比如说哈希表),用来记录爬虫已经访问过的链接。然后,只要在访问链接时把它们添加到哈希表里,如果链接已经在哈希表中,就不要再访问了(因为这意味着你已经去过这个链接了)。当然,还有一些更复杂的方法可以做到这一点,它们可能会让你的程序运行得更快,但实现起来也会更困难。
3
我现在已经不需要规则就能实现这个功能了。我给每个 start_url
加上了一个 meta
属性,然后自己检查这些链接是否属于原始域名,并相应地发送新的请求。
因此,我重写了 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']
,然后把这个域名和提取出来的链接进行比较,自己发送新的请求。