/ Align = "left" /

W moim poprzednim pytaniu , nie byłem zbyt szczegółowy w moim problemie (scraping z uwierzytelnionej sesji ze Scrapy), w nadziei, że będę w stanie wydedukować rozwiązanie z bardziej ogólnej odpowiedzi. Powinienem raczej użyć słowa crawling.

Oto Mój kod do tej pory:

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

Jak widzisz, pierwsza strona, którą odwiedzam, to strona logowania. Jeśli nie jestem jeszcze uwierzytelniony (w funkcji parse), wywołuję funkcję custom login, która formularz logowania. Następnie, jeśli jestem uwierzytelniony, chcę dalej raczkować.

Problem polega na tym, że funkcja parse, którą próbowałem nadpisać, aby się zalogować, teraz nie wykonuje już niezbędnych wywołań, aby zeskrobać kolejne strony (zakładam). I nie jestem pewien, jak zachować elementy, które tworzę.

Ktoś robił coś takiego wcześniej? (Authenticate, then crawl, using a CrawlSpider) Any help would be appreciated.
Author: Community, 2011-05-01

4 answers

Nie nadpisuj funkcji parse w CrawlSpider:

Kiedy używasz CrawlSpider, nie powinieneś nadpisywać funkcji parse. W dokumentacji CrawlSpider jest Ostrzeżenie: http://doc.scrapy.org/en/0.14/topics/spiders.html#scrapy.contrib.spiders.Rule

To dlatego, że z CrawlSpider, parse (domyślne wywołanie zwrotne dowolnego żądania) wysyła odpowiedź do przetworzenia przez Rule S.


Logowanie przed crawling:

Aby mieć jakiś rodzaj inicjalizacji, zanim pająk zacznie się czołgać, możesz użyć InitSpider (która dziedziczy po CrawlSpider) i zastąpić funkcję init_request. Ta funkcja zostanie wywołana, gdy pająk jest inicjalizacji, i zanim zacznie pełzać.

Aby Pająk zaczął się czołgać, musisz zadzwonić self.initialized.

Możesz przeczytać kod, który jest odpowiedzialny za to proszę. ( jest pomocny docstrings).


Przykład:

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 = ['example.com']
    login_page = 'http://www.example.com/login'
    start_urls = ['http://www.example.com/useful_page/',
                  'http://www.example.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..
            return 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

Zapisywanie elementów:

Przedmioty, które twój pająk zwraca są przekazywane do potoku, który jest odpowiedzialny za robienie z danymi, co chcesz. Polecam zapoznać się z dokumentacją: http://doc.scrapy.org/en/0.14/topics/item-pipeline.html

Jeśli masz jakieś problemy/pytania dotyczące Items, nie wahaj się otworzyć nowe pytanie, a ja Dołożę wszelkich starań, aby pomocy.

 57
Author: Acorn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-19 09:21:36

Aby powyższe rozwiązanie działało, musiałem sprawić, że CrawlSpider będzie dziedziczył z Initspidera, a nie z Basespidera, zmieniając, na scrapowym kodzie źródłowym, następujące elementy. W pliku scrapy/contrib/spiders/crawl.py:

  1. Dodaj: from scrapy.contrib.spiders.init import InitSpider
  2. Zmień class CrawlSpider(BaseSpider) na class CrawlSpider(InitSpider)

W przeciwnym razie pająk nie wywołałby metody init_request.

Czy jest jakiś inny łatwiejszy sposób?
 4
Author: viniciusnz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-12 14:08:58

Jeśli potrzebujesz uwierzytelniania Http użyj dostarczonych hooków oprogramowania pośredniczącego.

W settings.py

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

I w Twoim spider class Dodaj właściwości

http_user = "user"
http_pass = "pass"
 2
Author: bdargan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-27 20:25:35

Dodaję do powyższej odpowiedzi Acorn. Używając jego metody mój skrypt nie parsował start_urls po zalogowaniu. Kończyło się po pomyślnym zalogowaniu w check_login_response. Ale widziałem, że mam generator. I needed to to use

return self.initialized()

Następnie została wywołana funkcja parse.

 2
Author: knowingpark,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-15 04:37:15