Борьба с подвыбором xPath с помощью условий - PullRequest
0 голосов
/ 04 мая 2018

Я боролся с некоторыми манипуляциями с xPath в данный момент. У меня есть этот HTML-скребок в Python, который будет анализировать дерево HTML после определенного набора <li> и извлекать его text(). Проблема в том, что некоторые из этих <li> имеют <i class='ok'></i> без текста внутри.

<html>
  <body>
    <div>
     <ul>
       <li>Text...</li>
       <li>Other text...</li>
       <li><i class='ok'></i></li>
       <li><i class='ok'></i>Another text...</li>
     </ul>
    </div>
  </body>
</html>

Мой селектор xPath на данный момент выглядит следующим образом:

row_value = '(//div[contains(@id,"phone_columns")]' \
            '/div/ul[contains(@class,"phone_column_features")]' \
            '/li/text() | ' \
            '//div[contains(@id,"phone_columns")]' \
            '/div/ul[contains(@class,"phone_column_features")]' \
            '/li/i/@class)'

Я хочу получить значение класса в некоторых случаях, но большинство из них подойдет text().

Токовый выход:

[ "Text...", "Other text...", "ok", "ok", "Another text..." ]

Желаемый вывод:

[ "Text...", "Other text...", "ok", "ok Another text..." ]

Заранее спасибо, Цезарь Лидке

1 Ответ

0 голосов
/ 04 мая 2018

Обычно XPath, такой как //li/concat(i/@class, text()), должен справиться с задачей, но я вполне уверен, что lxml не поддерживает этот синтаксис.

Вместо этого вы можете использовать более сложный код:

source = lxml.html.fromstring(your_HTML)
li_nodes = source.xpath("//div/ul/li")  # replace this simplified XPath with actual XPath for li nodes

class_values = [i.xpath("./i/@class")[0] if i.xpath("./i/@class") else " " for i in li_nodes]
text_nodes = [i.text_content() if i.text_content() else " " for i in li_nodes]

output = [" ".join(item).strip() for item in zip(class_values, text_nodes)]

Выход print(output):

['Text...', 'Other text...', 'ok', 'ok Another text...']
...