Использование селектора scrapy с условиями - PullRequest
0 голосов
/ 10 ноября 2019

Я использую "scrapy", чтобы очистить несколько статей, подобных этим: https://fivethirtyeight.com/features/championships-arent-won-on-paper-but-what-if-they-were/
Я использую следующий код в моем пауке:

    def parse_article(self, response):
       il = ItemLoader(item=Scrapping538Item(), response=response)
       il.add_css('article_text', '.entry-content *::text')

... который работает. Но я бы хотел сделать этот CSS-селектор немного более сложным. Прямо сейчас я извлекаю каждый текстовый отрывок. Но, глядя на статью, там есть таблицы и визуализации, которые также включают текст. Структура HTML выглядит следующим образом:

<div class="entry-content single-post-content">
    <p>text I want</p>
    <p>text I want</p>
    <p>text I want</p>
    <section class="viz">
        <header class="viz">
            <h5 class="title">TITLE-text</h5>
            <p class="subtitle">SUB-TITLE-text</p>
        </header>
        <table class="viz full"">TABLE DATA</table>
    </section>
    <p>text I want</p>
    <p>text I want</p>
</div>

С кодом, приведенным выше, я получаю что-то вроде:

текст, который я хочу
текст, который я хочу
текст, который яхочу
TITLE-текст <<<< (текст, который я не хочу) <br>SUB-TITLE-текст <<<< (текст, который я не хочу) <br>ТАБЛИЦА ДАННЫХ <<<< (текстЯ не хочу) <br>текст Я хочу
текст Я хочу

Мои вопросы:

  • Как мне изменить функцию add_css() втаким образом, что он берет весь текст, кроме текстов из таблицы?
  • Было бы проще с функцией add_xpath?
  • В целом, что было бы лучшим для этого методом? (извлекать текст в условиях)

Обратная связь будет принята с благодарностью

Ответы [ 3 ]

0 голосов
/ 11 ноября 2019

Если я не пропустил что-то важное, следующий xpath должен работать:

import scrapy
import w3lib

raw = response.xpath(
    '//div[contains(@class, "entry-content") '
    'and contains(@class, "single-post-content")]/p'
).extract()

Это пропускает содержимое таблицы и дает только текст в параграфах и ссылки в виде списка. Но есть подвох! Поскольку мы не использовали /text(), все теги <p> и <a> все еще там. Давайте удалим их:

cleaned = [w3lib.html.remove_tags(block) for block in raw] 
0 голосов
/ 11 ноября 2019

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

.entry-content > *::text
0 голосов
/ 11 ноября 2019

Вы можете получить желаемый вывод с помощью XPath и оси ancestor:

'//*[contains(@class, "entry-content")]//text()[not(ancestor::*[@class="viz"])]'
...