Получить текст из XPath ближайшего ребенка - PullRequest
1 голос
/ 02 мая 2020

Я пытаюсь получить название продукта из следующей разметки:

<h2>
     <a href="https://example.com/item/ait-themes-anchor-wordpress-theme/">
             <span>AIT Themes</span> 
                   Anchor 
             <span>WordPress Theme for Campsites</span></a>
             <span class="version">2.0.0</span>
</h2>

Я хочу получить название продукта. В настоящее время я использую следующий xpath:

//a[@class="link-cover"]//parent::div/h2/a/text()

Но я получаю результат, который также находится внутри тега span. Это нежелательно.

[<Selector xpath='.//text()' data='AIT Themes'>, <Selector xpath='.//text()' data=' Solitudo '>, <Selector xpath='.//text()' data='WordPress Theme'>]
[<Selector xpath='.//text()' data='AIT Themes'>, <Selector xpath='.//text()' data=' Spa '>, <Selector xpath='.//text()' data='WordPress Theme'>]
[<Selector xpath='.//text()' data='AIT Themes'>, <Selector xpath='.//text()' data=' SportClub '>, <Selector xpath='.//text()' data='WordPress Theme'>]
[<Selector xpath='.//text()' data='AIT Themes'>, <Selector xpath='.//text()' data=' Sushi '>, <Selector xpath='.//text()' data='WordPress Theme'>]

Я пытался указать, какой элемент я хочу использовать в индексе.

response.xpath('//a[@class="link-cover"]//parent::div/h2/a/text()')[1]

Но это не очень хорошо работает, поскольку на этом конкретном c сайте есть страницы которые различаются по формату, но название продукта всегда находится внутри тега.

Я пытался использовать оператор "not" xpath, но ничего не возвращает.

//a[@class="link-cover"]//parent::div/h2/a/not(span)/text()

РЕДАКТИРОВАТЬ: Для справки, я вызываю xpath через scrap следующим образом:

    def parse_products(self, response):

        products = response.xpath('//a[@class="link-cover"]//parent::div/h2/a')

        for product in products:

            name = product.xpath('.//text()')[1].get()
            link = product.xpath(".//@href").get()

            yield {
                "product_name": name,
                "product_link": link,
                "product_developer": response.request.meta['developer'],
                "product_category": response.request.meta['category']
            }

        next_page = response.xpath(
            '//nav[@class="navigation pagination"]/div[@class="nav-links"]/a[@class="next page-numbers"]/@href').get()
        if next_page:
            yield scrapy.Request(url=next_page, callback=self.parse_products, meta={
                "developer": response.request.meta['developer'],
                "category": response.request.meta['category']
            })

1 Ответ

1 голос
/ 02 мая 2020

Просто используйте //h2/a/text()[normalize-space()]. Полное выражение XPath для вашего сайта:

//div[@class="new-post-display new-posts2"]//h2/a/text()[normalize-space()]

Вывод:

 Anchor 
 Aqua 
 Architect 
 Arctica 
 Aspiration 
 BandZone 
 Barcelona 
 BeachClub 
 Brick 
 BusinessFinder+
 ...

EDIT : Ваше выражение XPath работает в оболочке scrapy.

Selectors

Получить данные:

Extract

Я думаю, что проблема в вашем коде паука. Вы опубликовали это в результате:

[<Selector xpath='.//text()' data='AIT Themes'>,...

Замените в своем пауке .//text() на ./text(), и вы должны быть в порядке.

Sidenote: если вы хотите использовать индекс , исправьте свой XPath соответственно:

response.xpath('//a[@class="link-cover"]//parent::div/h2/a/text()[1]')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...