Как получить тег HTML на основе регулярного выражения - PullRequest
1 голос
/ 09 февраля 2012

Я пытаюсь извлечь каждый тег HTML, включая совпадение с регулярным выражением.Например, предположим, что я хочу получить каждый тег, включая строку «имя», и у меня есть HTML-документ, подобный этому:

<html>
  <head>
    <title>This tag includes 'name', so it should be retrieved</title>
  </head>
  <body>
    <h1 class="name">This is also a tag to be retrieved</h1>
    <h2>Generic h2 tag</h2>
  </body>
</html>

Возможно, мне следует попробовать регулярное выражение, чтобы перехватить каждое совпадение между открытием и закрытием"<>", однако, я хотел бы иметь возможность просматривать проанализированное дерево на основе этих совпадений, чтобы я мог получить братьев и сестер или родителей или 'nextElements'.В приведенном выше примере это равняется <head>*</head> или, возможно, <h2>*</h2>, как только я узнаю, что они являются родителями или братьями и сестрами тега, содержащего совпадение.

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

Предложения?

Ответы [ 2 ]

2 голосов
/ 10 февраля 2012

Использование lxml.html. Это отличный парсер, он поддерживает xpath , который может выражать все, что вы захотите легко.

В приведенном ниже примере используется это выражение xpath:

//*[contains(text(),'name']/parent::*/following-sibling::*[1]/*[@class='name']/text()

Это значит, на английском языке:

Найдите мне любой тег, который содержит слово 'name' в его тексте, затем получите родитель, а затем следующий брат и найти внутри этого любой тег с классом 'name' и, наконец, вернуть текстовое содержимое этого.

Результат выполнения кода:

['This is also a tag to be retrieved']

Вот полный код:

text = """
<html>
  <head>
    <title>This tag includes 'name', so it should be retrieved</title>
  </head>
  <body>
    <h1 class="name">This is also a tag to be retrieved</h1>
    <h2>Generic h2 tag</h2>
  </body>
</html>
"""

import lxml.html
doc = lxml.html.fromstring(text)
print doc.xpath('//*[contains(text(), $stuff)]/parent::*/'
    'following-sibling::*[1]/*[@class=$stuff]/text()', stuff='name')

Обязательно прочитайте, ответ "пожалуйста, не разбирайте HTML с регулярным выражением" здесь: https://stackoverflow.com/a/1732454/17160

1 голос
/ 10 февраля 2012

С учетом следующих условий:

  • Соответствие должно происходить по значению атрибута в теге
  • Соответствие должно происходить в текстовом узле, который является прямым потомком тега

Вы можете использовать красивый суп:

from bs4 import BeautifulSoup
from bs4 import NavigableString
import re

html = '''<html>
  <head>
    <title>This tag includes 'name', so it should be retrieved</title>
  </head>
  <body>
    <h1 class="name">This is also a tag to be retrieved</h1>
    <h2>Generic h2 tag</h2>
  </body>
</html>'''

soup = BeautifulSoup(html)
p = re.compile("name")

def match(patt):
    def closure(tag):
        for c in tag.contents:
            if isinstance(c, NavigableString):
                if patt.search(unicode(c)):
                    return True
        for v in tag.attrs.values():
            if patt.search(v):
                return True
    return closure

for t in soup.find_all(match(p)):
    print t

Выход:

<title>This tag includes 'name', so it should be retrieved</title>
<h1 class="name">This is also a tag to be retrieved</h1>
...