想象一下,我正在爬行foo.com
。 foo.com有几个内部链接,它有一些外部链接,如:
foo.com/hello
foo.com/contact
bar.com
holla.com
我想scrapy抓住所有的内部链接,但也只有一个深度的外部链接,如我想scrapy去bar.com
或holla.com
但我不希望它去bar.com
内的任何其他链接所以只有一个深度。
这可能吗?这种情况的配置是什么?
谢谢。
你可以将你的蜘蛛基于CrawlSpider
类,并使用Rule
s实现process_links
方法,你传递给Rule
。该方法将在跟踪之前过滤不需要的链接。来自documentation:
process_links
是一个可调用的或一个字符串(在这种情况下,将使用来自具有该名称的蜘蛛对象的方法),将使用指定的link_extractor
为每个响应中提取的每个链接列表调用。这主要用于过滤目的。
不是内置的解决方案,但我相信你必须自己打断递归。你可以通过在蜘蛛中保留一个域(一组)域并中断或忽略来轻松实现这一点。
某种东西:
from urllib.parse import urlparse
self.track = set()
...
domain = tracktraurlparse(response.url).netloc
x.add(domain)
if len(x) > MAX_RECURSION:
x.remove(domain)
# raise StopIteration (# if you're within a generator)
return None
我通过将参数传递给回调函数找到了解决方案。如果url是内部链接,我将flag设置为true(否则为false)。如果flag返回false(外部链接),则爬网程序不会提取新链接。这是我的示例代码:
class BrokenLinksSpider(CrawlSpider):
name = test
start_urls = "your_url"
def parse(self, response):
flag = response.meta.get('flag')
if flag or flag==None:
extractor = LinkExtractor(deny_domains="")
links = extractor.extract_links(response)
for link in links:
if link.url[:8]=="your_url":
new_request = Request(link.url, callback=self.parse,meta={'flag': True})
else:
new_request = Request(link.url, callback=self.parse,meta={'flag': False})
yield new_request