Сканирование с завершенным сеансом в Scrapy

В моем предыдущем вопросе я не был очень специфичен по моей проблеме (соскабливание с проверенной сессией с помощью Scrapy), в надежде на то, что вы сможете вывести решение из более общего ответа. Вероятно, я предпочел бы использовать слово « crawling .

Итак, вот мой код:

  • Использование Middleware для игнорирования дубликатов в Scrapy
  • Scrapy: динамически определять элементы
  • Как использовать scrapy для сканирования нескольких страниц?
  • Инициализация объекта трубопровода с помощью сканера в режиме
  • Scrapy и прокси
  • Как я могу использовать несколько запросов и передавать элементы между ними в scrapy python
  •  class MySpider(CrawlSpider): name = 'myspider' allowed_domains = ['domain.com'] start_urls = ['http://www.domain.com/login/'] rules = ( Rule(SgmlLinkExtractor(allow=r'-\w+.html$'), callback='parse_item', follow=True), ) def parse(self, response): hxs = HtmlXPathSelector(response) if not "Hi Herman" in response.body: return self.login(response) else: return self.parse_item(response) def login(self, response): return [FormRequest.from_response(response, formdata={'name': 'herman', 'password': 'password'}, callback=self.parse)] def parse_item(self, response): i['url'] = response.url # ... do more things return i 

    Как вы можете видеть, первая страница, которую я посещаю, – это страница входа. Если я еще не аутентифицирован (в функции parse ), я вызываю свою пользовательскую функцию login , которая отправляется в форму входа. Затем, если я аутентифицирован, я хочу продолжить сканирование.

    Проблема в том, что функция parse я пытался переопределить для входа в систему, теперь больше не делает необходимые вызовы для очистки любых последующих страниц (я предполагаю). И я не уверен, как сэкономить Предметы, которые я создаю.

    Кто-нибудь сделал что-то подобное раньше? (Аутентификация, а затем обход, с помощью CrawlSpider ). Любая помощь будет оценена по достоинству.

  • Инициализация объекта трубопровода с помощью сканера в режиме
  • Сканирование нескольких доменов с помощью Scrapy без criss-cross
  • Scrapy - Отфильтрованный дублированный запрос
  • Избегание перенаправления
  • Загрузка изображений с помощью scrapy
  • Как использовать scrapy для сканирования нескольких страниц?
  • 4 Solutions collect form web for “Сканирование с завершенным сеансом в Scrapy”

    Не переопределяйте функцию parse в CrawlSpider :

    Когда вы используете CrawlSpider , вы не должны переопределять функцию parse . В документации CrawlSpider есть предупреждение: http://doc.scrapy.org/en/0.14/topics/spiders.html#scrapy.contrib.spiders.Rule

    Это связано с CrawlSpider , что с помощью CrawlSpider parse (по умолчанию обратный вызов любого запроса) отправляет ответ, который должен обрабатываться Rule s.


    Вход в систему перед сканированием:

    Чтобы иметь какую-то инициализацию до того, как паук начнет сканирование, вы можете использовать InitSpider (который наследуется от CrawlSpider ) и переопределить функцию init_request . Эта функция будет вызываться, когда паук инициализируется, и до того, как он начнет сканирование.

    Чтобы Паук начал сканирование, вам нужно вызвать self.initialized .

    Вы можете прочитать код, который отвечает за это здесь (у него есть полезные docstrings).


    Пример:

     from scrapy.contrib.spiders.init import InitSpider from scrapy.http import Request, FormRequest from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor from scrapy.contrib.spiders import Rule class MySpider(InitSpider): name = 'myspider' allowed_domains = ['domain.com'] login_page = 'http://www.domain.com/login' start_urls = ['http://www.domain.com/useful_page/', 'http://www.domain.com/another_useful_page/'] rules = ( Rule(SgmlLinkExtractor(allow=r'-\w+.html$'), callback='parse_item', follow=True), ) def init_request(self): """This function is called before crawling starts.""" return Request(url=self.login_page, callback=self.login) def login(self, response): """Generate a login request.""" return FormRequest.from_response(response, formdata={'name': 'herman', 'password': 'password'}, callback=self.check_login_response) def check_login_response(self, response): """Check the response returned by a login request to see if we are successfully logged in. """ if "Hi Herman" in response.body: self.log("Successfully logged in. Let's start crawling!") # Now the crawling can begin.. self.initialized() else: self.log("Bad times :(") # Something went wrong, we couldn't log in, so nothing happens. def parse_item(self, response): # Scrape data from page 

    Сохранение предметов:

    Элементы, возвращаемые вашим Пауком, передаются вместе с Pipeline, который отвечает за выполнение того, что вы хотите сделать с данными. Я рекомендую вам ознакомиться с документацией: http://doc.scrapy.org/en/0.14/topics/item-pipeline.html

    Если у вас есть какие-либо проблемы / вопросы в отношении Item , не стесняйтесь вскрыть новый вопрос, и я сделаю все возможное, чтобы помочь.

    Чтобы работа над этим решением работала, мне пришлось сделать CrawlSpider наследованием от InitSpider и больше не использовать BaseSpider, изменив в исходном коде scrapy следующее. В файле scrapy / contrib / spiders / crawl.py:

    1. добавить: from scrapy.contrib.spiders.init import InitSpider
    2. измените class CrawlSpider(BaseSpider) на class CrawlSpider(InitSpider)

    В противном случае паук не будет вызывать метод init_request .

    Есть ли еще более простой способ?

    Если вам нужна Http Authentication, используйте предоставленные перехватчики промежуточного слоя.

    в settings.py

     DOWNLOADER_MIDDLEWARE = [ 'scrapy.contrib.downloadermiddleware.httpauth.HttpAuthMiddleware'] 

    и в вашем spider class добавьте свойства

     http_user = "user" http_pass = "pass" 

    Просто добавив ответ Acorn выше. Используя его метод, мой скрипт не анализировал start_urls после входа в систему. Он был завершен после успешного входа в систему check_login_response. Я мог видеть, что у меня был генератор. Мне нужно было использовать

     return self.initialized() 

    затем вызывается функция синтаксического анализа.

    Python - лучший язык программирования в мире.