我有一只蜘蛛,在蜘蛛开始时以小allowed_domains
列表开头。我需要动态地向这个白名单中添加更多域,因为蜘蛛从解析器中继续进行,但由于后续请求仍在被过滤,因此下面的一段代码无法完成。在解析器中是否有另一个更新allowed_domains
?
class APSpider(BaseSpider):
name = "APSpider"
allowed_domains = ["www.somedomain.com"]
start_urls = [
"http://www.somedomain.com/list-of-websites",
]
...
def parse(self, response):
soup = BeautifulSoup( response.body )
for link_tag in soup.findAll('td',{'class':'half-width'}):
_website = link_tag.find('a')['href']
u = urlparse.urlparse(_website)
self.allowed_domains.append(u.netloc)
yield Request(url=_website, callback=self.parse_secondary_site)
...
答案 0 :(得分:7)
(在撰写此答案的那一刻,scrapy
的最新版本为1.0.3
。此答案适用于所有最新版本的scrapy
)
由于OffsiteMiddleware
仅在处理allowed_domains
信号时初始化预编译的正则表达式对象时才读取spider_opened
中的内容,因此以后永远不会访问allowed_domains
中的值。 />
因此,简单地更新allowed_domains
的内容不会解决问题。
基本上,需要两个步骤:
allowed_domains
的内容。OffsiteMiddleware
刷新正则表达式缓存。以下是我用于步骤2的代码:
# Refresh the regex cache for `allowed_domains`
for mw in self.crawler.engine.scraper.spidermw.middlewares:
if isinstance(mw, scrapy.spidermiddlewares.offsite.OffsiteMiddleware):
mw.spider_opened(self)
上面的代码应该在响应回调中调用,因此self
这里应该是蜘蛛类的一个实例。
另见:
答案 1 :(得分:1)
您可以尝试以下内容:
class APSpider(BaseSpider):
name = "APSpider"
start_urls = [
"http://www.somedomain.com/list-of-websites",
]
def __init__(self):
self.allowed_domains = None
def parse(self, response):
soup = BeautifulSoup( response.body )
if not self.allowed_domains:
for link_tag in soup.findAll('td',{'class':'half-width'}):
_website = link_tag.find('a')['href']
u = urlparse.urlparse(_website)
self.allowed_domains.append(u.netloc)
yield Request(url=_website, callback=self.parse_secondary_site)
if response.url in self.allowed_domains:
yield Request(...)
...