Динамически добавлять в allow_domains в Scrapy Spider - PullRequest
3 голосов
/ 02 марта 2011

У меня есть паук, который начинается с небольшого списка allowed_domains в начале паука.Мне нужно динамически добавлять больше доменов в этот белый список, так как spiderring продолжается из синтаксического анализатора, но следующий фрагмент кода не достигает этого, поскольку последующие запросы все еще фильтруются.Есть ли другое обновление 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 ]

7 голосов
/ 08 октября 2015

(В тот момент, когда написан этот ответ, последняя версия scrapy равна 1.0.3. Этот ответ будет работать для всех последних версий scrapy)

Поскольку OffsiteMiddleware читает содержимое в allowed_domains только при инициализации предварительно скомпилированного объекта регулярного выражения при обработке сигнала spider_opened, значения в allowed_domains никогда не будут доступны позже. Таким образом, простое обновление содержимого allowed_domains не решит проблему.

В основном требуется два шага:

  1. Обновите содержимое allowed_domains в соответствии с вашими потребностями.
  2. Обновите кэш регулярных выражений в 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 голос
/ 02 марта 2011

Вы можете попробовать что-то вроде следующего:

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(...)

...
...