Использование XPath в строках - PullRequest
2 голосов
/ 29 января 2020

Допустим, у нас есть следующий ответ из браузера:

<div>
  <tr id="1"></tr>
  <tr id="2">
  <!--
    <div class="A">AAA</div>
    <div class="C">BBB</div>
    <div class="C">CCC</div>
  -->
  </tr>
</div>

Получение строки комментария с использованием xpath в scrapy должно выглядеть примерно так:

response.xpath(//tr[@id="2"]/comment())

Итак, мой вопрос - есть ли простой способ извлечь значения тегов <div class="C"> внутри комментария? Один из способов - удалить теги комментариев в строке <!-- (...) --> и использовать библиотеку lxml.html, чтобы снова преобразовать результат в HTML и использовать в нем xpath, но я уверен, что это должен быть более простой способ. ..

Буду признателен за любую помощь. Ура!

Ответы [ 3 ]

2 голосов
/ 29 января 2020

Парсинг содержания комментария с lxml.html является хорошим решением на мой взгляд.

Python Код

from lxml import etree
from io import StringIO

parser = etree.HTMLParser()

html_text = """<div>
  <tr id="1"></tr>
  <tr id="2">
  <!--
    <div class="A">AAA</div>
    <div class="C">BBB</div>
    <div class="C">CCC</div>
  -->
  </tr>
</div>"""

tree = etree.parse(StringIO(html_text), parser)

comment = tree.xpath("//tr[@id='2']/comment()")

comment_text = str(comment[0])

# string needs an outermost element in order to be parseable

comment_text = comment_text.replace("<!--", "<html>").replace("-->", "</html>")

embedded_tree = etree.parse(StringIO(comment_text), parser)

embedded_tree.xpath("//div[@class='C']/text()")

Вывод

['BBB', 'CCC']
1 голос
/ 31 января 2020

Хотя ответ есть, я бы хотел порекомендовать другое решение, поскольку оно действительно простое и подходит для извлечения данных из XML.

from simplified_scrapy.simplified_doc import SimplifiedDoc
html = '''
<div>
  <tr id="1"></tr>
  <tr id="2">
  <!--
    <div class="A">AAA</div>
    <div class="C">BBB</div>
    <div class="C">CCC</div>
  -->
  </tr>
</div>
'''
doc = SimplifiedDoc(html)
divs = doc.select('#2').selects('.C')
print ([div.text for div in divs])

Результат:

['BBB', 'CCC']

Вот еще примеры SimplifiedDo c здесь

0 голосов
/ 31 января 2020

Решение с одним вкладышем с XPath 2.0 (регулярное выражение можно, конечно, оптимизировать):

normalize-space(replace(normalize-space(//comment()),'(.div class="[^C]">.{3})|(.div class="C">)|(<.div>)',''))

Вывод:

'BBB CCC'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...