在Scrapy爬虫中动态添加allowed_domains

5 投票
2 回答
2913 浏览
提问于 2025-04-16 12:47

我有一个爬虫程序,它一开始有一个小的允许访问的域名列表(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里的内容是无法解决问题的。

基本上,需要两个步骤:

  1. 根据你的实际需求更新allowed_domains里的内容。
  2. 刷新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(...)

...

撰写回答