在Scrapy爬虫中动态添加allowed_domains
我有一个爬虫程序,它一开始有一个小的允许访问的域名列表(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)
...
2 个回答
10
在写这个回答的时刻,scrapy
的最新版本是1.0.3
。这个回答适用于所有最近版本的scrapy
。
因为OffsiteMiddleware
在处理spider_opened
信号时,只在初始化预编译的正则表达式对象时读取allowed_domains
里的内容,所以之后不会再访问allowed_domains
里的值。
因此,仅仅更新allowed_domains
里的内容是无法解决问题的。
基本上,需要两个步骤:
- 根据你的实际需求更新
allowed_domains
里的内容。 - 刷新
OffsiteMiddleware
中的正则表达式缓存。
这是我用来完成第二步的代码:
# 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
你可以试试下面这样的做法:
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(...)
...