Используя scrapy и учитывая этот HTML-код

<div class="parts"> 
<b>Part1 :</b> 
<a href='/part1.htm'>name 1</a> 
<br> 
<b> Part2 : </b> 
<a href='/part21.htm'>name 21</a>, 
<a href='/part22.htm'>name 22</a>, 
<a href='/part23.htm'>name 23</a>
<br> 
<b> Part3 : </b> 
<a href='/parts31.htm'>name 31</a>, 
<a href='/part32.htm'>name 32</a> 
<br>
</div>

Я хотел бы выделить каждую серию имен после каждого раздела <b>.

Для первого (где есть только одно имя) работает с этим

response.xpath('//div[@class="parts"]/b[contains(text(),"Part1")]/following::a/text()').extract_first()

В результате получается "имя 1"

Что касается второго, я ожидал, что следующее даст мне список с 'name 21', 'name 22' и 'name 23', то есть остановка перед следующим тегом b, но возвращенный список содержит также 'name 31' и 'name 32 '

response.xpath('//div[@class="parts"]/b[contains(text(),"Part2")]/following::a/text()')

Как я могу ограничить список только тем, что находится после тега b 'Part2' и перед тегом b 'Part3'?

1
Archipelago 15 Сен 2018 в 23:54

2 ответа

Лучший ответ

Один из способов выбрать все дочерние элементы text() для <a> между <b>, содержащим Part2, и <b>, содержащим Part3:

/div/b[contains(., 'Part2')]/following-sibling::a[following-sibling::b[contains(.,'Part3')]]/text()

Другой способ - выбрать всех text() потомков <a>, которые являются следующими братьями и сестрами для <b>, которые содержат Part2, и которые являются первым предшествующим братом {{X4 }} содержит Part2:

/div/b[contains(., 'Part2')]/following-sibling::a[preceding-sibling::b[1][contains(.,'Part2')]]/text()
0
Mads Hansen 16 Сен 2018 в 00:36

Я рекомендую вам использовать другой подход: просто получите ВСЕ имена и для каждого имени получите соответствующий раздел <b>:

data = {}
for name_node in response.xpath('//div[@class="parts"]/a'):
    name = name_node.xpath('./text()').extract_first()
    section_name = name_node.xpath('./preceding-sibling::b[1]/text()').extract_first()

    if section_name not in data:
        data[section_name] = []
    data[section_name].append(name)

print(data["Part2 :"][1])
0
gangabass 16 Сен 2018 в 01:14