Как использовать ограниченный текст в скрапе? - PullRequest
1 голос
/ 15 апреля 2020

Моя цель - извлечь ссылки только из части сайта (один узел HTML).

Из домена "quotes.toscrape.com" Я хочу извлечь ссылки, содержащие в себе "страницу" , Например: http://quotes.toscrape.com/page/3/

Я пытался добиться этого, передавая 'page' в регулярном выражении следующим правилам: allow, allow_domain и restrict_text. Я использовал эти комбинации регулярных выражений (r'page ', r' / page / ', r' [^] page [^] ', r'. * Page. * ') И другие. Последние два работают хорошо согласно https://regex101.com/. Похоже, что ни один из них не работает в моем коде.

Ниже вы можете увидеть последнее исполнение

class MySpider(CrawlSpider):
    name = 'quotes.toscrape.com'
    allowed_domains = ['quotes.toscrape.com']
    start_urls = ['http://quotes.toscrape.com/']

    rules = (
        Rule(LinkExtractor(restrict_text=r'.*page.*'), callback='parse'),
    )

    def parse(self, response):
        for span in response.css('span'):
            yield {
                'span': span.css('span::text').get(),
            }
        for div in response.css('div'):
            yield {
                'div': div.css('div::text').get(),
            }
        next_url_path = response.css(
            "a::attr('href')").extract()
        for item in next_url_path:
            yield scrapy.Request(response.urljoin(item), callback=self.parse)

Отрывок из документации Scrapy: https://docs.scrapy.org/en/latest/topics/link-extractors.html

restrict_text ( регулярное выражение (или список из) ) - одно регулярное выражение (или список регулярных выражений), которому текст ссылки должен соответствовать, чтобы быть извлеченным. Если он не указан (или пуст), он будет соответствовать всем ссылкам. Если указан список регулярных выражений, ссылка будет извлечена, если она соответствует хотя бы одному.

Буду признателен за подсказку о том, как правильно использовать restrict_text или любое другое правило для достижения той же цели.

1 Ответ

0 голосов
/ 16 апреля 2020

Ваше регулярное выражение верно, а проблема в другом. у вашего кода есть небольшие проблемы.

Я изменил код на это:

import scrapy
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor


class MySpider(CrawlSpider):
    name = 'quotes.toscrape.com'
    allowed_domains = ['quotes.toscrape.com']
    start_urls = ['http://quotes.toscrape.com/']

    rules = (
        Rule(LinkExtractor(allow=r'.*page.*'),
             callback='parse_page', follow=True),
    )

    def parse_page(self, response):
        yield {'url': response.url} # It just for test. can be omitted.
        for span in response.css('span'):
            yield {
                'span': span.css('span::text').get(),
            }
        for div in response.css('div'):
            yield {
                'div': div.css('div::text').get(),
            }

Сначала в LinkExtractor вы должны использовать allow=, а не restrict_text=, потому что allow= для URL-адресов, а restrict_text= для текста ссылки, а не для URL-адресов.

Во-вторых, вы не можете вызвать метод parse из-за этого предупреждения здесь :

При написании правил паука для обхода избегайте использования parse в качестве обратного вызова, поскольку CrawlSpider использует сам метод parse для реализации своей логики c. Так что если вы переопределите метод разбора, паук сканирования больше не будет работать.

Поэтому я изменил parse на parse_page и перезвонил ему.

В-третьих, Вам не нужно извлекать ссылки в методе parse и отправлять запрос оттуда. CrawlSpider сделать это автоматически. запросы, отправленные методом parse вручную, не соответствуют определенному вами rules.

Наконец, я предлагаю использовать это регулярное выражение. Это проще и чаще:

rules = (
        Rule(LinkExtractor(allow='page'),
             callback='parse_page', follow=True),
    )

Удачи!

...