scrapy может проверить, имеет ли ожидаемый тег только следующий брат или сестра?

#python #html #web-scraping #scrapy #nextsibling

#python #HTML #очистка веб-страниц #scrapy #nextsibling

Вопрос:

Позвольте мне опубликовать часть html, которую я хочу очистить первой

 <div id="hello">
  <p>abc</p>
  <center><img src="image_url"></center>
  <p align="center" style="text-align: center;"><b>def</b></p>
  <center><img src="image_url"></center>
  <p align="center" style="text-align: center;"><b>def</b></p>
  <p>abc</p>
  <p align="center" style="text-align: center;"><b>def</b></p>
  <center><img src="image_url"></center>
  <p align="center" style="text-align: center;"><b>def</b></p>
  <p>abc</p>
  <center><img src="image_url"></center>
</div>
  

Я пытаюсь очистить текст в p и src изображения, которое является image_url по порядку.
Дело в том, что HTML, который я показал выше, на самом деле не статичен, все страницы имеют разную структуру, что означает, что иногда будет больше p тегов, прежде чем появится center тег, который включает img src

Поскольку теги p и center случайным образом структурированы на каждой странице, я думал получить все p теги, например, с помощью response.css('#hello p') затем перебирать все p теги, чтобы получить текст, но при получении текста из текущего p тега во время цикла также проверьте, есть ли у next sibling center тег, если есть, то src добавьте его.

Я нашел что-то подобное, выполнив p.xpath('following-sibling::center[1]/img/@src').get() поскольку p — это каждый абзац, соответствующий итерации.

Но я подумал, что это вообще не работает, потому что, скажем, если у меня есть 4 p тега до center , я на самом деле получу 4, img src потому что это p.xpath('following-sibling::center[1]/img/@src').get() не просто находит следующего брата или сестру, но просматривает всех братьев и сестер после и проверяет, соответствует ли center тег.

Я попытался погуглить, но я не вижу ничего, что упоминало бы только проверку, является ли следующий брат каким-либо тегом. У кого-нибудь есть идеи, как я могу заставить его работать, чтобы я мог сохранять данные последовательно?

Надеюсь, мое объяснение имеет смысл.

Заранее спасибо за любую помощь и предложения

Комментарии:

1. Итак, вы хотите очистить center узел, только если он является непосредственным братом p , верно? p.xpath('following-sibling::*[1][name()="center"]/img/@src') Решает вашу проблему?

2. @JaSON great:D это действительно то, что мне нужно, можете ли вы опубликовать его, чтобы я мог пометить его как ответ? Но у меня есть еще один вопрос, который я забыл упомянуть, который я решил с помощью цикла, но интересно, есть ли другой способ? В моем сценарии выше после p может быть один center , но что, если их несколько? Есть ли простой способ сделать это вместо зацикливания, чтобы проверить, есть ли следующее изображение? Прямо сейчас я увеличиваю center[1] на единицу, чтобы увидеть, является ли return None или нет

3. Я не могу предоставить вам общее решение. Для 2 возможных center узлов подряд это будет following-sibling::*[(position()=1 and name()="center") or (position()=2 and name()="center" and not(preceding-sibling::*[1][name()="p"]))]/img/@src . Чем больше узлов может быть — тем более сложным и грязным будет XPath 🙂

Ответ №1:

Попробуйте ниже XPath, чтобы получить требуемый результат

 p.xpath('following-sibling::*[1][name()="center"]/img/@src')